【问题标题】:Could someone explain the logical error in this program?有人可以解释这个程序中的逻辑错误吗?
【发布时间】:2020-07-12 12:58:49
【问题描述】:
#include <stdio.h>

int main() {
    int a = 5, *p, **q, b;
    p = &a;
    q = p;
    b = *q;
    printf("%d", b);
}

我想找出这些分配在内存级别是如何出错的。假设a的地址是100p = &amp;a 是一个正确的分配。然后p 将指向地址100。我对q = pb = *q 的陈述感到困惑。他们怎么错了?

【问题讨论】:

  • q 应该是 q = &amp;p 而不是 q = pb 应该是 b = **q 而不是 b = *q

标签: c pointers memory


【解决方案1】:

p = &amp;a; 是正确的。 - 将a的地址分配给指针p

q = p; 错误(类型冲突)。 - 您尝试将指针 (*) 分配给指向指针 (**) 的指针。它应该是q = &amp;p,这样您就可以获得p 的地址并将其分配给指向指针q 的指针。

b = *q; 错误(类型冲突)。 - 您尝试将指针(*q 获得 p)分配给 int 对象。将a的值赋给b应该是b = **q;


如果您使用符合标准且最新的编译器编译此代码,它会向您显示所有冲突并且可能已经回答了您的大部分问题。

下次发布之前,尝试使用 GCC 或 Clang 之类的编译器执行您的代码,并查看它通过诊断消息告诉您的内容。

如果您不想在您的计算机上安装编译器包或 IDE,尽管强烈推荐,您可以使用 GodboltOnlineGDB 在线编译。

编译器是您查找语法问题的最佳朋友。特别是如果您使用更多的帮助查找标志,如-Wall-Wextra-Werror。 :-)

【讨论】:

  • 这个答案的后半部分不合适。没有迹象表明 OP 忽略了编译器消息。 OP 通过在问题中明确承认这一点,表明他们知道这些陈述是错误的。问题是问如何他们在“记忆水平”上是错误的。想必,OP 想更多地了解指针和指针的实现,而不仅仅是“这些赋值违反了类型规则”。而这个答案并没有说明这一点。
  • @EricPostpischil 对我来说,有一个明确的迹象表明 OP 确实错过了编译这段代码。 OP 没有提供来自编译器的任何结果消息,也没有谈到对这些消息的混淆。该部分的诊断非常清楚,因此几乎不需要进一步解释它们。如果情况仍然如此,OP 会询问消息的含义,但这里不是这种情况。相反,他/她要求“有人可以解释这个程序中的逻辑错误吗?”和“他们怎么错了?”这可能已经被编译器诊断清楚地回答了.
  • @RobertSsupportsMonicaCellio:如果您要求编译器指出您的错误,编译器是您最好的朋友...默认设置过于宽松,仍然需要额外的警告才能正确标记友谊,您可能想要记录最简单的:-Wall -Wextra -Werror
  • @chqrlie 将其纳入答案。谢谢。
【解决方案2】:

q 的类型为int** - 它是一个指向指针的指针。编译器会向您发出警告,因为您将 p(类型 int*)的值分配给类型 int**

应该是:

   q=&p;
   b=**q;

【讨论】:

    【解决方案3】:
    #include<stdio.h>
    int main()
    {
       int a=5,*p,**q,b;    #1
       p=&a;                #2
       q=p;                 #3
       b=*q;                #4
       printf("%d",b);      #5
    }
    
    1. #1中,您已声明整数数据类型a 并将其初始化为5。假设它在内存中的地址为0x100p 是整数指针并且没有初始化(今天的一些(不是全部)编译器将它作为一个特性,并将其初始化为 NULL但你不应该依赖它,你应该将其显式初始化为 NULL !),q 是指向整数指针的指针,并且未初始化(与之前的注释相同),b 是未初始化的整数。
    2. #2中,您将a 的地址分配给p,所以现在p 指向内存中的a。因此,p 值为:0x100
    3. #3中,您将p(即int 指针)分配给指向int 指针的指针!这是错误的,但编译器会让你通过警告:warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]。这个warning 的修复是q=&amp;p;。由于这只是警告,q 指向0x100
    4. b 是整数,您正在分配它,*q,这是 q 的值,在这种情况下是 0x100(您不能将内存地址分配给 int 变量)并且它是类型为int pointer!同样,这是错误的,但编译器会让你通过警告:warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]。你应该做b = **qb 的值现在是:(*q) 这是 *(&amp;p) 这是 *(0x100) 这是 5
    5. 打印b的值,因此打印5

    【讨论】:

    • 关于“今天的编译器为你完成工作并将其初始化为 null”:不,他们没有,这是一个危险的陈述,因为它会导致程序员编写带有错误的软件。也许有些编译器有这个特性,但它肯定不是普遍正确的,不应该依赖于没有特定的编译器文档。
    • @EricPostpischil - 我没这么说。但我会改进我的答案。谢谢。
    • @EricPostpischil - 已修复。谢谢。你。你能删除否决票吗?
    • @Adam 当地习俗强烈反对拉票。
    • @RobertSsupportsMonicaCellio:在这段代码中并不重要。这对你教给未来程序员的东西很重要。如果你告诉未来的程序员编译器会初始化一个自动对象,而编译器没有初始化一个自动对象,那么他们未来的程序就会有错误。
    猜你喜欢
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 2020-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多