我有一个问题,我对我得到的输出感到困惑。有人可以帮我解决这个问题。
`
#include <stdio.h>
int main()
{
int *i = 5;
char *c = i[1];
printf("%c", *c);
}
`
它会正确编译而不会出错。如果它编译,它会在运行时给出分段错误。如果是,因为哪一行。据我说,main()的前两行是好的。 printf语句给出了分段错误,但我无法证明它是正确的。这里int * i初始化为常量。所以我可以将'我'指向其他位置,但不能改变*我。我将'i'的第二个字节分配给char * c,但在这里我没有改变* i。那么为什么打印* c给出了分段错误。这是我的观点。寻找更好的解释。
答案 0 :(得分:2)
通过执行int *i = 5;
,您会得到指向无效内存地址的指针。只要你不在其上做指针算术,那就没关系了,并且不要取消引用它。
通过执行char *c = i[1];
,您可以在该指针上执行指针算术(指向的对象不是数组),甚至可以取消引用它。两者都意味着您正在调用未定义的行为。同时声明一个初始化另一个指向无效内存地址的指针。
通过执行printf("%c", *c);
,您再次取消引用无效的指针地址,该地址再次调用未定义的行为。也就是说,任何事情都可能发生,包括分段错误。
请注意,您只会观察到分段错误,因为您在知道此类恶意代码形式的操作系统上运行并拒绝其进一步执行。未定义的行为不能保证失败。问题是,编译器不需要通知您有关代码的此类问题。
答案 1 :(得分:1)
int *i = 5;
创建一个指向地址 5的指针,而不是指向数字的地址 5.您应该这样做:
int a = 5;
int *i = &a;
此外,由于i
是指向int
的指针,因此以下行为未定义:
char *c = i[1];
// ^ returns an int, not a char pointer
答案 2 :(得分:0)
您可以 NOT 从静态值初始化指针。您的代码初始化i
以指向内存地址5
,这肯定不是您的应用程序内存。要做你想做的事,你需要这个:
int x = 5;
int* i = &x;
&
是获取int x
地址的运算符的地址,其中包含值5
。至于你的第二行,那是完全无效的。指向int
的指针不支持[]
运算符,即使它是一个数组。你要么:
i
的价值:*i
i
的第一个字节:除非你有充分的理由否则不要尝试然后,将该值赋给指针,该指针也无效。您需要再次使用&
。
答案 3 :(得分:0)
您的代码存在一些问题。
int *i = 5;
您正在使用地址初始化指针i
。此问题至少存在一些问题。首先,大多数现代体系结构(例如x86)都坚持要对齐int
等多字节类型,以便它们在偶数地址上开始。其次,5是一个非常低的地址值,并且取决于平台可能无法用于您的程序(使其成为无效的地址)。
char *c = i[1];
现在,您正在声明指向char
的指针,并使用i
之后的下一个整数地址存储的整数的值进行初始化(7或9或一些其他地址,如上所述已经存在问题;这本身可能导致分段错误)。除了输入问题(表达式i[1]
的类型是int
,而不是char *
)之外,几乎可以保证i[1]
的内容是一个随机位字符串,而不是printf
对应有效的内存地址。
这就是你在*c
语句中得到分段错误的原因; main
正试图取消引用无效指针。
所以不,{{1}}的前两行绝对不是好的。