user-0 提问: 字符串的小问题

回复:
user: user-1
content: 引用 10 楼 MikeDDT009 的回复:[quote=引用 4 楼 cfjtaishan 的回复:] 数组长度不是位，字符数组每个元素都是一个字节。 第二个问题，str1能够正常输出但不等于就是对的，可以这样做的。把str2拷贝至str1中是越界的。所以strcpy没有strncpy安全。 建议不要这么做，在strcpy函数介绍里，就已经有提示了，目的缓存要大于源字符串的长度；至少要是strlen(src)+1个长度。误些单位，是我不够严谨了，就是因为这里示例，源数组里存储的字符是按照字符串常量进行的初始化，那么就应该有个‘\0’字符，而目标数组明显只有9字节大小，既只能存9个字符，那么源数组复制过去，按理来说是不对的，但是却没报错，我还以为是我理解错了，而产生的疑惑[/quote] 这是随机性的，小程序不出问题，不等于在大程序里这样做不出问题。对于越界就是一个bug,很容易出问题。

user: user-0
content: 引用 6 楼 xiaohuh421 的回复:char str1[9],str2[]={"Microsoft"};    strcpy(str1,str2)  因为没有\0的存放位置了  char str[6]=“CHINA”;   //这叫初始化,   (定义的时候同时赋值, 这是正确的)  str[6] = “CHINA”;    // 这是赋值了, 是错误的.    字符串变量的赋值,   只能一次赋值一个字符. 并且索引从0开始, 只能赋值0-5.   比如  str[0]= 'C'; str[1]='H'; str[2] = 'I'; ....  要一次性赋值, 就只能使用函数   strcpy(str, "CHINA"); 原来如此，也就是说翻看的老教材太不够严谨了，直接赋值那个的确是我自己写的不够严谨，原来是char str[5]="CHINA"这样的

user: user-0
content: 引用 4 楼 cfjtaishan 的回复:数组长度不是位，字符数组每个元素都是一个字节。 第二个问题，str1能够正常输出但不等于就是对的，可以这样做的。把str2拷贝至str1中是越界的。所以strcpy没有strncpy安全。 建议不要这么做，在strcpy函数介绍里，就已经有提示了，目的缓存要大于源字符串的长度；至少要是strlen(src)+1个长度。误些单位，是我不够严谨了，就是因为这里示例，源数组里存储的字符是按照字符串常量进行的初始化，那么就应该有个‘\0’字符，而目标数组明显只有9字节大小，既只能存9个字符，那么源数组复制过去，按理来说是不对的，但是却没报错，我还以为是我理解错了，而产生的疑惑

user: user-0
content: 引用 1 楼 gametheory1010 的回复:char str[6];//定义是正确的 str[6] = "CHINA"； //这样赋值不正确。下标是从 0 开始的， 从str[0]到str[5]，每一位代表一个字符。 //只有初始化的时候才可以直接赋值字符串。  是我表述不够清楚，我意思就是在初始化的时候进行赋值，就是针对str[5]="CHINA"这个来说的，字符串有个‘\0’，而字符串数组只有5个，也既5字节大小，存储了CHINA这几个字符后  引用 4 楼 cfjtaishan 的回复:数组长度不是位，字符数组每个元素都是一个字节。 第二个问题，str1能够正常输出但不等于就是对的，可以这样做的。把str2拷贝至str1中是越界的。所以strcpy没有strncpy安全。 建议不要这么做，在strcpy函数介绍里，就已经有提示了，目的缓存要大于源字符串的长度；至少要是strlen(src)+1个长度。 引用 4 楼 cfjtaishan 的回复:数组长度不是位，字符数组每个元素都是一个字节。 第二个问题，str1能够正常输出但不等于就是对的，可以这样做的。把str2拷贝至str1中是越界的。所以strcpy没有strncpy安全。 建议不要这么做，在strcpy函数介绍里，就已经有提示了，目的缓存要大于源字符串的长度；至少要是strlen(src)+1个长度。函数说明是那样，但是下面那个代码示例的情况让人纠结，纠结的地方在于前者9个字节，存了后者的字符以后，不会有一个字符串的结尾'\0'吗，主要在于前面看字符串常量的时候字符‘a’和字符串“a”是不一样的，前者一个字节，而后者存储所占位置是2个字节，自带‘\0’字符

user: user-2
content: 有时候越界运行的时候不出错并不代表你这样做没错，只能说明你运气好

user: user-3
content: char str1[9],str2[]={"Microsoft"};    strcpy(str1,str2)  因为没有\0的存放位置了  char str[6]=“CHINA”;   //这叫初始化,   (定义的时候同时赋值, 这是正确的)  str[6] = “CHINA”;    // 这是赋值了, 是错误的.    字符串变量的赋值,   只能一次赋值一个字符. 并且索引从0开始, 只能赋值0-5.   比如  str[0]= 'C'; str[1]='H'; str[2] = 'I'; ....  要一次性赋值, 就只能使用函数   strcpy(str, "CHINA");

user: user-4
content: 越界不是编译错误，运行是没崩只能算运气好，仅此

user: user-1
content: 数组长度不是位，字符数组每个元素都是一个字节。 第二个问题，str1能够正常输出但不等于就是对的，可以这样做的。把str2拷贝至str1中是越界的。所以strcpy没有strncpy安全。 建议不要这么做，在strcpy函数介绍里，就已经有提示了，目的缓存要大于源字符串的长度；至少要是strlen(src)+1个长度。

user: user-5
content: 引用 6 楼 xiaohuh421 的回复:char str1[9],str2[]={"Microsoft"};    strcpy(str1,str2)  因为没有\0的存放位置了  char str[6]=“CHINA”;   //这叫初始化,   (定义的时候同时赋值, 这是正确的)  str[6] = “CHINA”;    // 这是赋值了, 是错误的.    字符串变量的赋值,   只能一次赋值一个字符. 并且索引从0开始, 只能赋值0-5.   比如  str[0]= 'C'; str[1]='H'; str[2] = 'I'; ....  要一次性赋值, 就只能使用函数   strcpy(str, "CHINA");正解

user: user-6
content: 其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

user: user-7
content: 前者是初始化  str[5]="CHINA"这是赋值语句，字符串数组不能这样子赋值的，str[5] 表示的是取str的第六个字符 就是是 str[100]="CHINA"那也不正确  strcpy不考虑你目标字符串缓存是否足够，编译的时候也不会报错 如果目标缓存不足以存储下源字符串  运行的时候可能完全无误，也可能对其他堆栈数据造成破坏，更严重的会导致程序直接崩溃 是一个不可预知的bug，慎重对待

user: user-8
content: 缓存不足，不代表一定报错，可能会错误地占用其它堆栈，比较危险，但不是一定会导致进程挂掉。

user: user-9
content: char str[6];//定义是正确的 str[6] = "CHINA"； //这样赋值不正确。下标是从 0 开始的， 从str[0]到str[5]，每一位代表一个字符。 //只有初始化的时候才可以直接赋值字符串。