我有一个C编程语言的代码段,如下所示:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char *s="Abhas";
printf(" s = %s \n", s);
printf(" s + s[1] = %s \n", s+s[1]);
printf(" s + s[1] - s[3]= %s \n", s+s[1]-s[3]);
return 0;
}
,输出为:
那么,你能帮我澄清一下我们如何得到第二个和最后一个输出线。我是C的新人。
答案 0 :(得分:4)
printf(" s + s[1] = %s \n", s+s[1]);
相当于:
printf(" s + s[1] = %s \n", s+'b');
相当于:
printf(" s + s[1] = %s \n", s+98);
这将访问它不应该的内存。该程序表现出不确定的行为。
该行:
printf(" s + s[1] - s[3]= %s \n", s+s[1]-s[3]);
相当于:
printf(" s + s[1] - s[3]= %s \n", s+`b'-'a`);
相当于:
printf(" s + s[1] - s[3]= %s \n", s+1);
相当于:
printf(" s + s[1] - s[3]= %s \n", "bhas");
因此输出。
答案 1 :(得分:2)
想想这样的记忆:
| [0] | [1] | [2] | [3] | [4] | [5] | <- indexes
+-----+-----+-----+-----+-----+-----+
s: | A | b | h | a | s | nul | <- characters
| 65 | 98 | 104 | 97 | 115 | 0 | <- integral values (if ASCII)
+-----+-----+-----+-----+-----+-----+
以下表达式 - 地址映射显示了正在发生的事情:
s -> s -> &(s[0])
s + s[1] -> s + 98 -> &(s[98])
s + s[1] - s[3] -> s + 98 - 97 -> s + 1 -> &(s[1])
其中,只有第一个和第三个是合法的,因为它们最终在字符串的范围内。第二个是未定义的。
第一个为您提供字符串本身的地址,因此您会看到Abhas
。
第三个字符为您提供字符串第二个字符的地址,因此您会看到bhas
。
第二个给你一些不错的字符串,因此会给你任何想要的东西。事实上,作为未定义的行为,它可以为你提供任何东西,没有任何东西,崩溃,格式化你的磁盘,疯狂地通过你的声卡笑,甚至崩溃到一个赤裸裸的奇点,占据我们星球的一大块。
我当然应该提到,除了教你如何使用指针之外,该代码应该从不在野外使用或看到。这是不如何编码的经典示例。