繁体   English   中英

使用 malloc 将值分配给 C 指针,无需变量初始化

[英]Assigning values to C pointers using malloc without variable initialization

这个问题,我明白为什么下面的代码可能不起作用:

int *ptr;
*ptr = 1000;
printf("%d", *ptr);

当我编译并运行它时使用: gcc file.c; ./a.out gcc file.c; ./a.out我得到:

分段错误(核心转储)./a.out

这里的 ptr 可能指向一个没有初始化变量的随机位置。 那是对的吗?

但是,使用malloc()时不会出现该问题。

int *ptr = malloc(sizeof(int));
*ptr = 1000;
printf("%d", *ptr);

malloc 是否初始化其指针指向的变量?

简短的回答:没有

malloc 不初始化变量。 它只是分配 memory。 您可以将 integer 放入 function 中,例如malloc(8) ,它只会分配 8 个字节供以后使用。 如果您进一步查看 malloc function,它实际上返回void*数据类型。 它可以稍后被类型转换为其他数据类型。

从您的代码malloc(sizeof(int)) ,实际上sizeof(int)返回一个 integer 用于您放入其中的数据类型/变量的大小。

案例一
代码:

int *ptr;
*ptr = 1000;

*ptr表示您正在取消引用ptr指针。 取消引用未初始化的指针是未定义的行为 未定义的行为包括它可能执行不正确(崩溃或默默地生成不正确的结果),或者它可能偶然地完全按照程序员的意图执行。

案例二
代码:

int *ptr = malloc(sizeof(int));
*ptr = 1000;

malloc分配 memory 块(大小以字节为单位)并在成功时返回指向新分配的 memory 开头的指针。 memory 新分配的块初始化。

这样做时:

int *ptr = malloc(sizeof(int));

假设malloc调用成功,它返回指向新分配的 memory 开头的指针。 这个返回的指针将被分配给ptr指针。 因此,现在ptr指针已初始化,尽管它指向的 memory 是uninitialised
由于ptr指针指向一个有效的 memory 位置,因此您可以取消引用并访问它。

在这份声明中

*ptr = 1000;

取消引用ptr并将1000分配给该 memory 位置。 现在, ptr指针指向的 memory 位置包含值1000 访问这个值非常好。


额外的:

遵循良好的编程习惯 - 始终检查malloc返回。 你应该做:

  int *ptr = malloc (sizeof (int));
  if (NULL == ptr) {
    exit(EXIT_FAILURE); // or whatever you want to do at malloc failure do it here
  }

您链接的帖子或多或少地解释了它。 一件事是未定义的行为 - 这正是没有malloc的版本中会发生的情况。

如果您尝试使用这样的指针,各种各样的事情都会出错 - 您还没有说它应该指向哪里 它可以从字面上指向任何地方。

这一行:

int *ptr = malloc(sizeof(int));

确实是初始化。 这里发生的是两件事:(1) malloc在 memory 中保留空间,以便您随后可以使用指针和(2)它返回该 ZCD69B4957F06CD818D7BF3D61980E29 的起始地址

地址被分配给ptr - 它本身就是一个变量。 而且,像所有变量一样,您不能在未初始化的情况下使用它们。 如果这样做,那是无效的代码,因此会导致未定义的行为。

让我们再深入一点:

如果您不调用malloc ,则您的指针无效,不应使用。 为了证明这一点,请尝试编译您的代码,例如使用旧的gcc

如果你运行:

gcc program.c  # no flags

编译——但仅仅因为gcc给了你一个二进制文件,这并不意味着它会做你想做的事。 当你运行它时,它(大多数时候)会惨遭失败。

但是,如果您运行:

gcc -Wall program.c  # enable warnings

它会警告ptr未初始化未使用。 但是,它仍然会生成一个您可以运行的二进制文件 - 产生与以前相同的结果。

最后,如果你运行:

gcc -Wall -Werror program.c  # enable warnings and turn them into errors

它会再次警告你同样的事情,但这一次,它不会产生二进制文件——这就是你在这种情况下真正想要的。 在这里, gcc告诉你,有些事情确实非常错误,你的代码根本无效。

现在,回到关于未定义行为的话题。 一旦你编译了你的无效代码(使用前两种方法中的任何一种——顺便说一句,请永远不要这样做),运行它通常会给你一个“分段错误”(seg fault)。 然而,它不是必须的,也不能保证你的程序会做什么。 所有变量,包括指针,都需要初始化。

顺便说一句,如果您查看这篇文章,它会告诉您为什么需要在这里调用malloc ——因为您正在动态分配 memory,因此它将位于堆中而不是堆栈中。

暂无
暂无

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

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