【问题标题】:Casual value of a not initialized pointer to pointer未初始化的指向指针的指针的临时值
【发布时间】:2020-07-10 07:58:13
【问题描述】:

当我定义一个指针而不初始化它时:

int *pi;

它指向内存的随机部分。

当我定义一个指向指针而不初始化它的指针时会发生什么?

int **ppi;

它指向哪里?它应该指向另一个指针,但我没有定义它,所以它可能指向内存的随机部分?如果可能的话,你能用一个例子来说明一下不同之处吗?

【问题讨论】:

  • 它指向一个随机地址,与指针类型无关。
  • C 中任何未初始化的非静态变量都会有未确定的内容。由于pippi 是指针变量,它们的内容代表内存中的地址。所以,它们的值是不确定的,这些值基本上是内存中的随机地址。底层指针类型将决定如何解释这些地址所指向的内容,但这并不会改变这些只是内存中位置的事实。
  • 让我建议避免使用“随机”这个词来形容这种事情。一个未初始化的指针指向一个任意内存位置。它(可能)根本不是随机的。在某些系统上,它更可能是位置零而不是其他任何东西。其他一些系统可能会用一些可识别的模式填充其他未初始化的内存。

标签: c pointers initialization declaration


【解决方案1】:

为了清楚起见,请考虑以下声明

T *ptr;

其中T 是某个类型说明符。如果声明的变量ptr 具有自动存储持续时间,则指针不会显式​​或隐式初始化。

所以指针有一个不确定的值。

T 可以是任何类型。例如,您可以将 T 定义为

typedef int T;

typedef int *T;

指针是标量对象。因此在这个声明中

typedef int *T;
T *ptr;

指针ptr 具有与声明中相同的不确定值

typedef int T;
T *ptr;

【讨论】:

    【解决方案2】:

    任何未初始化的局部变量都包含一个不确定的值。不分类型。例如未初始化的intint*int** 之间没有明显区别。

    但是,C 中有一条规则说,如果您不访问此类未初始化的局部变量的地址,而是使用其值,则会调用未定义的行为 - 意味着错误,可能是崩溃等。基本原理是很可能这些变量可能被分配在寄存器中并且没有可寻址的内存位置。详情请见https://stackoverflow.com/a/40674888/584518

    所以下面的这些例子都是不好的和错误的,因为局部变量本身的地址从来没有被使用过:

    {
      int i;
      int* ip;
      int** ipp;
      printf("%d\n, i);          // undefined behavior
      printf("%p\n, (void*)ip);  // undefined behavior
      printf("%p\n, (void*)ipp); // undefined behavior
    }
    

    但是,如果您在某处获取变量的地址,则 C 不那么严格。在这种情况下,您最终会得到一个不确定值的变量,这意味着它可以包含任何内容,并且如果您多次访问它,该值可能会不一致。如果是指针,这可能是一个“随机地址”,但不一定如此。

    不确定的值可能是所谓的“陷阱表示”,即该类型的禁止二进制序列。在这种情况下,访问变量(读取或写入)会调用未定义的行为。这对于普通的int 不太可能发生,除非您有一个非常奇特的系统,它不使用 2 的补码 - 因为在标准 2 的补码系统中,int 的所有值组合都是有效的并且没有填充位,负零等。

    示例(假设 2 的补码):

    {
      int i;
      int* ip = &i;
      printf("%d\n", *ip);  // unspecified behavior, might print anything
    }
    

    未指定的行为意味着编译器不需要记录该行为。你可以得到任何类型的输出,它不需要是一致的。但至少程序不会像在未定义行为的情况下那样崩溃和烧毁。

    但是陷阱表示更可能是指针变量的事情。一个特定的 CPU 可能有一个受限的地址空间或在低级初始化,MMU 可以设置为具有某些虚拟区域,某些区域仅包含数据或某些区域仅包含代码等。即使您将无效地址值读入索引寄存器,CPU 也会产生硬件异常。如果您尝试通过无效地址访问内存,它肯定很有可能这样做。

    例如,MMU 可能会阻塞试图从内存数据段执行代码的失控代码,或者像访问数据一样访问代码内存的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-09
      • 2013-04-01
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 2015-04-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多