我有一个例子,我用字符串初始化 char 指针。我得到的一些行为在一种情况下有效,但在另一种情况下无效。我将用 3 个代码示例进行解释:
第第一个代码是这样的:
#include <stdio.h>
int main(void) {
char* f = "test";
printf("%s", f);//prints "test"
}
这段代码工作得很好,包含它的目的是为了表明我们可以用字符串初始化一个 char 指针并很好地打印它。
第第二个代码是这样的:
#include <stdio.h>
void strcpy(char* dst, char* src) {
int i = 0;
do {
*(dst + i) = *(src + i);
} while (*(src + (i++)));
}
int main(void) {
char first[] = "test2";
char second[] = "test3";
strcpy(second, first);
printf("%s", second); //prints "test2"
}
这段代码也可以正常工作。包含它的目的是因为下一行代码将不起作用。
第第三个代码是这样的:
#include <stdio.h>
void strcpy(char* dst, char* src) {
int i = 0;
do {
*(dst + i) = *(src + i);
} while (*(src + (i++)));
}
int main(void) {
char first[] = "test4";
char *second = "test5"; //ONLY THIS LINE IS CHANGED
strcpy(second, first);
printf("%s", second); //PRINTS NOTHING
}
你明白为什么第三个代码什么也不打印吗?它只是第一个和第二个示例的组合,所以我不明白为什么它不起作用?
char *second = "test5";
初始化 second
以指向由字符串文字创建的数组的第一个字符。关于字符串文字,C 2018 6.4.5 7 说:
…如果程序尝试修改这样的数组,则行为是未定义的。
由于您的程序在调用
strcpy(second, first);
时尝试修改数组,因此您的程序的行为未定义。
C 实现的常见行为是将字符串文字数组放入标记为进程只读的内存中,因此尝试修改它会导致内存访问冲突。
编译器优化还可能导致其他最初令程序员感到惊讶的行为,因为优化可能假设没有尝试修改字符串文字的数组,因此可能会基于该假设来转换程序。