当我想要进行手动字符串复制时,我发现以下代码片段令人困惑。
int strincmp(char *s1) {
int l1 = strlen(s1)+1;
char *s1_copy = malloc(sizeof(char) * l1);
while(*s1_copy++=*s1++);
printf("s1_copy = %s , s1 = %s \n",s1_copy,s1);
return 0;
}
输出很混乱,因为我希望它输出一个复制的字符串。但它如下:
s1_copy = , s1 =
当我替换" while(* s1_copy ++ = * s1 ++);"使用以下天真方式声明(将s1_copy和s1视为数组而不是ptrs)
int i=0;
while( s1[i] != '\0'){
s1_copy[i] = s1[i];
i++;
}
s1_copy[i] = '\0';
输出是我的预期。
s1_copy = TenaLynetta , s1 = TenaLynetta
这对我来说很困惑,为什么第一种方法不起作用。希望这是一个有意义的问题。
答案 0 :(得分:3)
使指针指向已分配内存的第一个位置
s1_copy
|
-----------------------------------
| h | e | l | l | o | \0 |
-----------------------------------
在while循环中,你继续递增指针,所以在while循环结束时,指针实际指向字符串的结尾,而不是指向字符串的开头。
s1_copy
|
-------------------------------------------
| h | e | l | l | o | \0 | ----- |
-------------------------------------------
%s
打印出字符串,直到遇到\0
字符。由于指针指向内存中某个不受您控制的位置,并且您尝试从那里打印字符串,因此会导致未定义的行为。
原始字符串也以相同的方式进行修改,但由于未定义的行为,您会看到正确/不正确的输出。
当存在未定义的行为时,您永远不知道实际发生了什么
答案 1 :(得分:0)
这是因为指针s1_copy和s1都递增并到达字符串的末尾(NULL字符'\ 0')。
或者您可以像这样使用它来保持指向字符串开头的指针并在结尾处打印它。(需要两个额外的指针,所以不太推荐)
int strincmp(char *s1) {
int l1 = strlen(s1)+1;
char *s1_dup = s1;
char *s1_copy = malloc(sizeof(char) * l1);
char *s1_copy_dup = s1_copy;
while(*s1_copy++=*s1++);
s1_copy = s1_copy_dup;
s1 = s1_dup;
printf("s1_copy = %s , s1 = %s \n",s1_copy,s1);
return 0;
}