gpt4 book ai didi

c - C中指针赋值的区别

转载 作者:行者123 更新时间:2023-11-30 21:35:04 24 4
gpt4 key购买 nike

下面显示的指针分配之间有什么区别:

int i = 5;
int *ptr = &i;

对比

int i = 5;
int *ptr;
ptr = &i;

对比

int i = 5;
int *ptr;
*ptr = &i;

我认为第一个和第二个是相同的,但第三个是不同的。所以我的问题是 1,2 与 3 之间有什么区别?

最佳答案

前两个语句执行相同的操作,但有一些原因(我将详细介绍)更喜欢第一种风格而不是第二种风格。第三种是未定义行为,这是非常糟糕的。它也应该是一个类型错误。

如果您的编译器毫不费力地接受此代码,则说明您没有在打开足够警告的情况下进行编译。它应该注意到您正在取消引用未初始化的指针,并且您正在将指针分配给 int没有 Actor 。在 gcc 或 clang 上,您可以添加标志 -Wall -Wextra -Wpedantic -Wconversion-std=c11或任何您的目标。

声明int i = 5;在第三种情况下,与接下来发生的事情基本上无关。声明int *ptr;是一个未初始化的指针。然后,*ptr = &i;取消引用该未初始化的指针,如果幸运的话,程序会立即崩溃,让您找到问题所在。如果你运气不好,它会在某个地方弄乱内存的其他部分,从而产生一个奇怪且不可预测的错误,你无法重现,也没有提示它来自哪里。

防御性编码的一个好习惯是编写尽可能多的变量作为静态单一赋值。也就是说,只要有可能,您就声明并初始化变量一次,如 const ,并且永远不要再次修改它们。在这种情况下,这将是:

const int i = 5;
const int * const ptr = &i;

这也消除了一大类错误,即我在本打算使用旧变量的情况下使用了变量的新值,反之亦然。编译器无法为我捕获这些。如果iptr只有一种含义,当我重构时,不可能混淆它在任何给定时间的含义。至于效率,那就是洗。如果我根据某个值进行计算,我要么再次需要原始值,要么不需要。如果我这样做,覆盖它就是一个错误。如果不这样做,依赖性分析应该确定编译器不需要再保留该值。

你不能总是这样做:一个非常常见的例子是循环计数器。在这些情况下,一个好的习惯(尽管你可以找到我没有严格遵循自己建议的例子)是始终将所有内容初始化为 0 , NULL或其他一些明显无效的值。这样,如果您在真正初始化之前不小心使用了它,至少结果将是错误的并且是可重现的。所以:

int i = 5;
int *ptr = NULL;
*ptr = &i; /* FIXME: Undefined behavior! */

在您要瞄准的大多数操作系统上,这至少会在发生逻辑错误的地方立即使您的程序崩溃,从而很容易找到它。 (因为,在过去,我的 C 和 C++ 答案引起了一两个人的注意,他们想指出语言标准不能保证这一点,我同意,它是不可移植的。但是我发现它在实践中很有用。)否则,如果您在调试器中单步执行,寻找错误,那么很明显该变量在使用时未初始化,而如果它只是包含堆栈上的任何垃圾,也可能不是。

另一方面,如果您的编译器可以检测到正在使用的未初始化变量,这种习惯可能会阻止它这样做。

关于c - C中指针赋值的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48821309/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com