const char* str1="abcd"与char* str2="abcd"的区别

这是CSDN论坛上一个讨论贴,觉得比较好,总结一下。

 

const char* str1="abcd"与char* str2="abcd"的区别:

(1)第一个在修改某个字符的时候会在编译时报错;第二个是在运行时报错(一般说来,不是绝对)。前者是一种良好的编程习惯。

(2)编译时str1[2] = '1'是非法的,str2[2] = '1'是合法的(在运行时会报错)。这种所谓的合法性,其实只是编译器为了兼容老代码而“伪报的合法”,实际上第二种情况是一种错误表达式,只是如果把它当成错误,很多很多C语言程序都要改,所以编译器才容忍了这种错误。好的程序员只写第一种。

(3)我们假定标准规定char * a ="abcd"合法,那么标准自己是矛盾的。大家都知道"abcd"不是变量,一个常量是不可能有非常量的地址的,而这个表达式的左侧是一个存储非常量地址的指针,标准怎么解释这种矛盾?我还想说一个事实,char * a= "abcd",依赖编译器的不同,"abcd"放的位置可能是只读存储区,在这种情况下a[2] = 'b'也许不会导致语法错误,但是会导致程序崩溃。低容忍是减少错误的最佳方法,我一向倾向于把char * a ="abcd"当作一个错误,只有这样严格要求自己,自己程序出错的可能性才更低。

(4)在C++中"aaa..."的类型明确是array of n const char,在C中没有提及其类型。C/C++对于相同的string literatl是否具有相同的存储,都是实现定义的。C/C++修改一个string literal是未定义的。C/C++存储都是static的。因此,在类型系统的方面,从C的角度来看,两都可以是正确的。从C++的角度来看,array of n const char to pointer to char这一步是有容忍的。在实际行为的方面两者都是容忍性的。

(5)需要说明的是:C是没有const的,因此char* a ="abcd"是无奈之举。而C++支持这个表达式一样是无奈的,因为C++不可能强迫所有的现存C程序都被重写,因此只能允许这种不精确而矛盾的C语法。这种C语法正确运行的前提是:任何人都不要试图通过这个指针改变那个string literal,而这个前提在复杂程序下是很难维护的,因为通过多层函数调用以后,你再也无法确定a是指向一个string lteral还是一个malloc/new出来的缓冲区。所以,新程序员避免写出这样的式子是非常非常重要的,许多“莫名其妙”的错误往往就由于你这种仔细而避免。

(6)第一种是指向常量的指针,不能通过指针来修改变量的值。第二种是一般的指针,通常下这样的指针应该指向一个变量,但这里初始化为一个常量,编译能通过(为了兼容以前的C代码),但运行时可能就会有些问题(如通过str2修改常量)。

(7)对于c中的string literal,无论c90和c99都是有所规定的,都规定为char,并没有const,因此在c中,char *p = "lskdjfk";是合法的。

(8)首先你声明了一个常量指针,然后你用一个字符串常量初始化它。当你试图修改某个字符的时候,编译器报错,因为你企图修改常量指针的指向对象。其次,你声明了一个普通指针,然后你用一个字符串常量初始化它。当你试图修改某个字符的时候,编译器显然允许你修改普通指针指向的对象,但是运行时发现你是想去静态存储区修改字符串常量,于是报错。

(9)引用 Thingking in C++的作者Bruce Eckel的回复:限定词const是很严格的,没有强调const的地方时字符数组的字面值。也许有人可以写:char* cp="howdy";编译器将接受它而不报告错误。从技术上讲这是一个错误,因为字符数组的字面值(这里是"howdy")是被编译器作为一个常量字符数组建立的,所引用该字符数组得到的结果是它在内存里得首地址。修改该字符数组里的任何字符都会导致运行时错误,当然,并不是所有编译器都会做到这一点。所以字符数组的字面值实际上是常量字符数组,当然编译器把它们作为非常量看待,这是因为有许多现有的C代码是这样做的。当然,改变字符数组的字面值的做法还未被定义,虽然可能在很多机器上时这样做的。如果想修改字符串,就要将它放到一个数组中:char cp[]="howdy"。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值