繁体   English   中英

关于C指针的说明

[英]clarification about C pointers

在以下示例中:

int *i;
*i=1;

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

我的问题是为什么要执行以下操作:

int *i=1;

只产生与整数转换有关的警告,而不会挂起程序?

为什么该指令不产生错误也没有警告?

char *s="acd";

如果我正在使用类似于之前的示例

谢谢

让我们分别讨论这三种情况:

int *i;
*i=1;

第一行为指针分配内存,但不初始化它,使i保留随机垃圾值。 第二行尝试写入由随机垃圾说明的内存地址,从而在运行时导致未定义的行为。

int *i=1;

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

顺便说一句,如果您要执行以下操作:

int *i=1;
*i=1;

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

char *s="acd";

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

您的第一种情况是您尝试写入内存的唯一情况:

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.
int *i = 1;

等效于:

int *i;
i = 1;

出于同样的原因:

char *s = "acd";

...相当于:

char *s;
s = "acd";

类型定义中星号的出现是表示is是指针的表示法。 这与您看到类型定义之外使用星号(表示取消引用)不同。

因此,在这些情况下,您只是在分配指针值本身,而不是对其进行解引用并写入其指向的内存。 指针本身的内存在堆栈上分配,因此被占用。 当您取消引用并在未正确初始化时尝试对其进行写操作时,会出现危险。

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

int *i;

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

*i = 1;

您访问由分配给名称i的内存位置中的值所给定的某些内存。 您可能没有访问该内存的权限,因此程序崩溃。

当你写

int *i = 1;

您声明了指针并将其初始化为指向内存位置1。请注意,您没有尝试将任何内容写入内存位置1,只需将i指向它即可。 如果您确实尝试对其进行写操作,则会再次出现段错误。

您的最后一种情况声明了一个字符指针,该字符指针指向字符串文字(因为"string"值等于该文字存储的地址),该地址通常存储在您有权读取但不能写入的内存的特殊部分中。

对于第一部分,声明:

int *i=1;

实际上与这样做相同:

int *i;
i=1;

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

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

在第一个例子中

int *i;
*i = 1;

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

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

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

在第一个示例中:

int *i;
*i=1;

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

在第二个示例中:

int *i = 1;

您正在将值1分配给指针值i-就是说我指向内存地址1。这等效于:

int *i;
i = 1;

发生警告是因为i的类型为int*且类型为int

在最后一个示例中:

char *s="acd";

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

int *i;

声明变量i为一个指向int的指针

*i = 1;

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

int *i = 1;

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

按照定义,像"acd"这样的字符串文字是一个以NULL结尾的char数组,其中包含字符串中的字符。 赋值时,此数组衰减为一个指向char的指针,并且在将其分配给char *时没有问题。 不过,我认为您不应该修改该数组的元素,因此最好将其分配给const char * ,gcc可能会很乐意警告您。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM