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
    评论
下面是实现上述函数的示例代码: ```c #include <stdio.h> char *my_strcpy(char *dest, char const *src) { char *temp = dest; while ((*dest++ = *src++)) ; return temp; } char *my_strncpy(char *dest, char const *src, int len) { char *temp = dest; while (len > 0 && (*dest++ = *src++)) { len--; } if (len > 0) { *dest = '\0'; } return temp; } char *my_strcat(char *dest, char const *src) { char *temp = dest; while (*dest) { dest++; } while ((*dest++ = *src++)) ; return temp; } char *my_strncat(char *dest, char const *src, int len) { char *temp = dest; while (*dest) { dest++; } while (len > 0 && (*dest++ = *src++)) { len--; } if (len > 0) { *dest = '\0'; } return temp; } int my_strcmp(char *str1, char const *str2) { while (*str1 && (*str1 == *str2)) { str1++; str2++; } return *(unsigned char *)str1 - *(unsigned char *)str2; } int my_strncmp(char *str1, char const *str2, int len) { while (len > 0 && *str1 && (*str1 == *str2)) { str1++; str2++; len--; } if (len == 0) { return 0; } return *(unsigned char *)str1 - *(unsigned char *)str2; } int main() { char dest[100] = "Hello"; char src[] = "World"; printf("strcpy: %s\n", my_strcpy(dest, src)); char dest2[100] = "Hello"; printf("strncpy: %s\n", my_strncpy(dest2, src, 3)); char dest3[100] = "Hello"; printf("strcat: %s\n", my_strcat(dest3, src)); char dest4[100] = "Hello"; printf("strncat: %s\n", my_strncat(dest4, src, 3)); char str1[] = "abc"; char str2[] = "abc"; printf("strcmp: %d\n", my_strcmp(str1, str2)); char str3[] = "abcd"; char str4[] = "abce"; printf("strncmp: %d\n", my_strncmp(str3, str4, 3)); return 0; } ``` 上述代码演示了如何实现 `my_strcpy`、 `my_strncpy`、 `my_strcat`、 `my_strncat`、 `my_strcmp` 和 `my_strncmp` 函数。你可以根据需要调用这些函数,并根据具体的参数和返回值进行相应的操作。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值