-2

我有一个问题,我对我得到的输出有点困惑。有人可以帮我解决这个问题。

`

#include <stdio.h>

int main()
{
  int *i = 5;
  char *c = i[1];
  printf("%c", *c);
}

`

它会正确编译而没有错误。如果它编译,它会在运行时给出分段错误。如果是,是因为哪一行。据我说, main() 的前两行是可以的。printf 语句给出了分段错误,但我无法证明它的合理性。这里 int *i 被初始化为一个常数。所以我可以将'i'指向其他位置但不能更改*i。我将 'i' 的第二个字节分配给 char *c,但这里我没有更改 *i。那么为什么打印 *c 会出现分段错误。这是我的看法。寻找更好的解释。

4

4 回答 4

2

通过这样做int *i = 5;,您会得到一个指向无效内存地址的指针。只要您不对它进行指针运算并且不取消引用它就可以了。

通过这样做char *c = i[1];,您确实对该指针(指向的对象不是数组)执行指针算术,甚至取消引用它。两者都意味着您正在调用未定义的行为。同时,您声明了一个初始化另一个指向无效内存地址的指针。

通过这样做printf("%c", *c);,您再次取消引用无效的指针地址,这再次调用未定义的行为。也就是说,任何事情都可能发生,包括分段错误。

请注意,您只观察到分段错误,因为您正在运行的操作系统知道这种形式的恶意代码并拒绝其进一步执行。未定义的行为不保证会失败。问题是,编译器不需要通知您有关代码的此类问题。

于 2012-07-17T20:10:43.593 回答
1

int *i = 5;创建一个指向地址5 的指针,而不是数字5 的地址。你应该这样做:

int a = 5;
int *i = &a;

此外,由于i是指向 a 的指针int,因此以下行为未定义:

char *c = i[1];
//        ^ returns an int, not a char pointer
于 2012-07-17T20:07:58.467 回答
0

您的代码有几个问题。

int *i = 5;

您正在i使用地址5 初始化指针。这至少有几个问题。首先,大多数现代体系结构(例如 x86)坚持多字节类型(例如,int对齐),以便它们从偶数地址开始。其次,5 是一个非常低的地址值,并且取决于平台,您的程序可能无法使用(使其成为无效地址)。

char *c = i[1];

现在,您要声明一个指向char并使用存储在下一个整数地址之后的整数值i 7 或 9 或其他地址,这已经存在问题,如上所述;这本身可能导致分段错误)。除了打字问题(表达式的类型i[1]int,不是char *)之外,几乎可以保证 的内容i[1]是不对应于有效内存地址的随机位字符串。

这就是为什么您在printf语句中得到分段错误的原因;*c正在尝试取消引用无效指针。

所以不,前两行main绝对不行

于 2012-07-17T20:25:14.900 回答
0

您不能静态值初始化指针。您的代码初始化i为指向内存地址5,这肯定不是您的应用程序内存。做你想做的事,你需要这个:

int x = 5;
int* i = &x;

是运算符的&地址,它获取 int 的地址x,它保存值5。至于你的第二行,那是完全无效的。指向intlike 的指针不支持该[]运算符,即使它是一个数组。你要么想要:

  • 的价值i*i
  • 的第一个字节i:除非你有充分的理由,否则不要尝试

然后,将该值分配给一个指针,这也是无效的。您需要&再次使用。

于 2012-07-17T20:12:22.677 回答