关于C指针的澄清

时间:2012-11-21 04:15:30

标签: c pointers

在以下示例中:

int *i;
*i=1;

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

我的问题是以下原因:

int *i=1;

只生成一个与整数转换相关的警告而不挂起程序?

为什么这条指令不会产生错误或警告?

char *s="acd";

如果我使用类似于之前的例子

由于

8 个答案:

答案 0 :(得分: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 *的自然事物,所以没有警告。

答案 1 :(得分: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.

答案 2 :(得分:1)

int *i = 1;

相当于:

int *i;
i = 1;

出于同样的原因:

char *s = "acd";

......相当于:

char *s;
s = "acd";

类型定义中星号的外观是表示is是指针的符号。这与您在类型定义之外使用星号时的区别不同,它表示取消引用。

所以在这些情况下,你只是指定指针值本身...不解除引用它并写入它指向的内存。指针本身的内存在堆栈上分配,因此被占用。当你取消引用并在没有正确初始化时尝试写入它时,你的危险就会出现。

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

答案 3 :(得分:0)

int *i;

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

*i = 1;

您可以访问由分配给名称i的内存位置中的值指定的内存。您可能无权访问该内存,因此程序崩溃。

写作时

int *i = 1;

声明指针并将其初始化为指向内存位置1.请注意,您尚未尝试将任何内容写入内存位置1,只是指向i。如果您尝试写入它,则会再次出现段错误。

你的最后一种情况是声明一个指向字符串文字的字符指针(因为"string"计算到存储该文字的地址),这通常存储在你有权读取的内存的特殊部分中,但不写。

答案 4 :(得分:0)

对于第一部分,声明:

int *i=1;

实际上和做的一样:

int *i;
i=1;

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

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

答案 5 :(得分:0)

在你的第一个例子中

int *i;
*i = 1;

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

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

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

答案 6 :(得分:0)

在第一个例子中:

int *i;
*i=1;

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

在第二个例子中:

int *i = 1;

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

int *i;
i = 1;

出现警告是因为我的类型为int*且类型为int

在最后的例子中:

char *s="acd";

您正在指定s指向字符串文字。字符串文字存储在程序的静态内存中,因此在运行时它将替换为有效的地址。 stirng文字的类型为char*,与s的类型相同,因此没有警告。

答案 7 :(得分:0)

int *i;

声明变量i是指向int的指针,而

*i = 1;

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

int *i = 1;

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

根据定义,像"acd"这样的字符串文字是一个NULL - 终止的char数组,其中包含字符串中的字符。在赋值时,此数组衰减为指向char的指针,当您将其指定给char *时,没有任何问题。我不认为你应该修改那个数组的元素,所以最好把它分配给const char *,gcc可能很乐意警告你。