0

在以下示例中:

int *i;
*i=1;

它会产生一个挂起的程序,因为我知道我正在将一个值直接放入内存位置。

我的问题是为什么如下:

int *i=1;

只产生与整数转换相关的警告并且不挂起程序?

为什么这条指令既不产生错误也不产生警告?

char *s="acd";

如果我使用与之前的示例类似的东西

谢谢

4

8 回答 8

3

让我们分别谈谈这3个案例:

int *i;
*i=1;

第一行为指针分配内存,但不初始化它,给 i 留下一个随机垃圾值。第二行尝试写入由随机垃圾拼出的内存地址,导致运行时出现未定义的行为。

int *i=1;

这为指针分配内存并为其分配值 1(即内存地址0x1)。由于这将整数值 1 隐式转换为指针,因此您会收到警告,因为将指针初始化为非空内存地址的情况极为罕见。

顺便说一句,如果你要这样做:

int *i=1;
*i=1;

它会尝试将值 1 写入内存地址0x1,从而导致与第一种情况相同的未定义行为。

char *s="acd";

这会在堆栈上创建一个以 null 结尾的字符串并让 s 指向它。字符串文字是分配给 char * 的自然事物,因此没有警告。

于 2012-11-21T04:21:59.813 回答
2

您的第一个案例是您尝试写入内存的唯一案例:

int *i; // i is a pointer but it's value is undefined
*i = 1; // Whoops, you just wrote to a random memory location.

int *i=1; // i is an invalid pointer (address 1), but you aren't writing to it

char *s="acd"; // s points to the string literal "acd" - again: no write.
于 2012-11-21T04:20:42.210 回答
1
int *i = 1;

相当于:

int *i;
i = 1;

出于同样的原因:

char *s = "acd";

...相当于:

char *s;
s = "acd";

类型定义中星号的出现是表示它的符号,i并且s是指针。这与您看到在类型定义之外使用的星号不同,星号表示取消引用。

因此,在这些情况下,您只是分配指针值本身......而不是取消引用它并写入它指向的内存。指针本身的内存是在堆栈上分配的,因此被占了。当您取消引用并在未正确初始化时尝试写入时,您的危险就来了。

请注意,对于字符串,您可以取消对它的引用。当编译器看到字符串文字时,四个内存字符acd\0被隐式留出......然后将文字评估为该内存的地址。所以你的s指针很好。您的i指针是一个任意值,在大多数系统上很可能不可读。

于 2012-11-21T04:23:49.637 回答
0
int *i;

声明一个指针。如果在函数中完成,这是一个自动变量并且未初始化。然后当你尝试

*i = 1;

您访问由分配给 name 的内存位置中的值给出的一些内存i。您可能没有访问该内存的权限,因此您的程序崩溃了。

当你写

int *i = 1;

您声明指针并将其初始化为指向内存位置 1。请注意,您没有尝试将任何内容写入内存位置 1,只是指向i它。如果您确实尝试写入它,您将再次遇到段错误。

您的最后一个案例声明了一个指向字符串文字的字符指针(因为"string"计算结果为存储该文字的地址),该字符串通常存储在您有权读取但无权写入的内存的特殊部分中。

于 2012-11-21T04:22:14.667 回答
0

对于第一部分,声明:

int *i=1;

实际上和做的一样:

int *i;
i=1;

也就是说,指针 i 被声明为位于内存位置 1(如果您有 32 位地址空间,则为 0x00000001)。警告仅仅是因为您将整数转换为地址。

对于第二部分,它是声明字符串的正确语法。这就是为什么它不会触发错误。

于 2012-11-21T04:22:37.357 回答
0

在你的第一个例子中

int *i;
*i = 1;

您声明一个指针并让它未初始化。即未初始化意味着它基本上具有随机值,因此指针指向随机内存位置。然后您尝试将该位置的内存设置为一个值,这可能会使您的程序崩溃。使用未初始化的指针是未定义的行为

在第二个示例中,您实际上初始化了指针。您没有在i指向的位置分配值,但实际上i 指向内存地址1

第三个示例只是第二个示例的变体,您可以在其中告诉指针s指向存储文字字符串的内存"acd"

于 2012-11-21T04:22:58.620 回答
0

在第一个示例中:

int *i;
*i=1;

您将 1 分配给 i 指向的位置,该位置未初始化,因此它很可能写入无效的位置。

在第二个例子中:

int *i = 1;

您将值 1 分配给指针值 i - 也就是说,您说 i 指向内存地址 1。这相当于:

int *i;
i = 1;

出现警告是因为 i 是 typeint*并且是 type int

在最后一个例子中:

char *s="acd";

您正在分配 s 以指向字符串文字。字符串文字存储在程序的静态内存中,因此在运行时它被替换为有效地址。搅拌文字的类型是char*,它是相同的类型,s所以没有警告。

于 2012-11-21T04:24:57.090 回答
0
int *i;

将变量声明i为指向intwhile的指针

*i = 1;

尝试将整数 1 存储在存储在的任何地址i。当您在存储任何内容之前执行此命令时i,这应该是未定义的行为。它可能i包含一些随机值,因此您试图将 1 存储在随机地址。

int *i = 1;

将变量声明i为指向 an 的指针int并尝试将该指针初始化为 1。由于 1 是整数而不是整数的地址,因此您会收到警告。

"acd"根据定义,字符串字面量是一个包含字符串中字符的以 - 结尾的数组NULLchar在分配时,该数组衰减为指向 a 的指针char,并且当您将其分配给 achar *时,没有问题。不过,我认为您不应该修改该数组的元素,因此最好将其分配给 a const char *,gcc 可能会很乐意警告您。

于 2012-11-21T04:27:32.360 回答