【问题标题】:Do C pointers (always) start with a valid address memory?C 指针(总是)是否以有效的地址存储器开头?
【发布时间】:2019-03-19 15:36:28
【问题描述】:

C 指针(总是)是否以有效的地址存储器开头?例如,如果我有以下代码:

int *p;
*p = 5;
printf("%i",*p); //shows 5

为什么这段代码有效?根据书籍(我读过的),他们说指针总是需要一个有效的地址内存并给出以下类似的例子:

int *p;
int v = 5;  
p = &v;
printf("%i",*p); //shows 5

【问题讨论】:

  • 因为此类代码的行为未定义,所以任何事情都可能发生。包括匹配预期结果的程序输出。
  • “为什么这段代码有效?” - 它没有;您将观察到的行为定义的行为混淆了。您的代码破坏了后者,因此您最终可能会观察到一些看似有效但没有定义行为的脊椎来确保它会起作用的东西。
  • 即使是坏掉的时钟一天也能正确两次。
  • @Lundin 你链接到一个 C++ 标记的问题。我们不希望新手认为 C++ 就是 C,对吗?

标签: c pointers memory


【解决方案1】:

C 指针是否(总是)以有效的地址存储器开始?

没有。

为什么这段代码有效?

代码调用未定义的行为。如果它似乎在您的特定系统上与您的特定编译器选项一起工作,那只是巧合。

【讨论】:

  • ..以及加载程序/操作系统如何准备内存,或者在您的程序之前驻留在内存中的程序。
【解决方案2】:

没有。未初始化的局部变量具有不确定的值,并且在对其求值的表达式中使用它们会导致未定义的行为。

【讨论】:

    【解决方案3】:

    行为未定义。 C 编译器可以优化指针访问,注意在 fact 中不使用p,仅使用对象*p,并将*p 替换为@ 987654324@并有效生成对应本源代码的程序:

    #include <stdio.h>
    
    int main(void) {
        int q = 5;
        printf("%i", q); //shows 5
    }
    

    当我使用 GCC 7.3.0 和 -O3 开关编译程序时就是这种情况 - 没有崩溃。如果我编译它没有优化,我会崩溃。这两个程序都是符合标准的代码解释,即解引用一个指向有效对象的指针具有未定义的行为

    【讨论】:

      【解决方案4】:

      没有。

      在过去,初始化指向选定内存地址(例如链接到硬件)的指针是很常见的。

      char *start_memory buffer = (char *)0xffffb000;
      

      编译器无法确定这是否是有效地址。这涉及演员表,所以它是作弊。

      考虑

      static int *p;
      

      p 将具有 NULL 值,它不指向有效地址(Linux,但在内核上,它使该地址无效,其他操作系统可以使用 &amp;NULL 上的内存来存储一些数据。

      但您也可以创建初始化变量,因此使用未定义的初始值(这可能是错误的)。

      【讨论】:

        猜你喜欢
        • 2014-10-03
        • 1970-01-01
        • 1970-01-01
        • 2018-06-12
        • 2020-11-08
        • 1970-01-01
        • 2019-11-11
        • 1970-01-01
        相关资源
        最近更新 更多