【问题标题】:C - Uninitialized pointer -> pointing to an array [duplicate]C-未初始化的指针->指向数组[重复]
【发布时间】:2016-03-12 13:05:19
【问题描述】:

我对以下代码有疑问:

#include <stdio.h>

int main() {
    int i;

    char char_array[5] = "abcde";
    int int_array[5] = {1, 2, 3, 4, 5};

    char *char_pointer;
    int *int_pointer;

    for(i=0; i < 5; i++) {
        printf("[integer pointer] points to %p, which contains the integer %d\n", int_pointer, *int_pointer);
        int_pointer = int_pointer + 1;
    }

    for(i=0; i < 5; i++) {
        printf("[char pointer] points to %p, which contains the char '%c'\n", char_pointer, *char_pointer);
        char_pointer = char_pointer + 1;
    }
}

我没有初始化任何指针,只是设置了指针的类型。这两个指针指向数组的正确内存地址,并从位置[0]开始。

使用 Ubuntu 7.04 和 gcc 编译器。

如果我运行代码,我会得到以下结果:

[integer pointer] points to 0xbffff7f0, which contains the integer 1
[integer pointer] points to 0xbffff7f4, which contains the integer 2
[integer pointer] points to 0xbffff7f8, which contains the integer 3
[integer pointer] points to 0xbffff7fc, which contains the integer 4
[integer pointer] points to 0xbffff800, which contains the integer 5
[char pointer] points to 0xbffff810, which contains the char 'a'
[char pointer] points to 0xbffff811, which contains the char 'b'
[char pointer] points to 0xbffff812, which contains the char 'c'
[char pointer] points to 0xbffff813, which contains the char 'd'
[char pointer] points to 0xbffff814, which contains the char 'e'

我知道这不是正确的编程风格,你不应该让指针未初始化,但是我遇到了这个并想问你,为什么指针知道他必须指向哪个地址而不初始化。

我还在代码 int_array2 和 char_array2 中添加了两个数组,第一个在 int_array/char_array 之后,第二个在 int_array/char_array 之前。但我仍然得到相同的结果...

也许有人知道这背后的魔力。提前感谢您抽出宝贵时间回答我的问题。

【问题讨论】:

  • 您的代码格式错误,无法编译。你是说第7行的)=吗?
  • 抱歉,我猜这是因为我的虚拟机出现了复制和粘贴问题。我现在就改。
  • 第6行和第7行没用,但也有问题。主要问题是两个未初始化的指针。
  • 未定义行为意味着 C 编程语言标准没有指定程序在给定一段源代码时应该如何表现。您将获得的结果将取决于语言的实现(编译器,链接器,...),但在这种情况下,指针和数组彼此相邻存储在堆栈上,因此您可以访问数组通过指针操作。

标签: c arrays pointers initialization


【解决方案1】:

首先,您可能知道,这种行为在标准中称为未定义行为。

从标准的角度来看,这个程序可能会移除你的整个硬盘,发射核导弹,或者给你的老板发一封非常糟糕的邮件。 但是,通常会导致程序失败。

现在回到你的案例 - 我认为它的发生是因为以下一个或多个选项:

  1. 您的编译器按类型对变量内存进行分组。
  2. 您的编译器按对齐大小对变量内存进行分组。

现在它仍然不是很好的理由,但也许这个分组是因为当变量没有初始化时编译器代码中有不必要的行。编译器的这个变量也可能未初始化:-)

【讨论】:

  • 似乎这是一个没有大惊小怪的正确答案。添加一些汇编代码就可以了。
【解决方案2】:

当局部变量未初始化时,这些变量的内容为undefined

这意味着这些变量的内容无法预测。尝试阅读它们可能会输出一些意想不到的东西,或者可能看起来有效。在指针变量的情况下,取消引用通常会导致核心转储,但不一定。

这就是为什么在尝试读取(或取消引用)变量之前始终初始化变量很重要的原因。

OpenSSL 就是一个使用未初始化的变量可能会反过来影响您的示例。他们故意将某些变量未定义为随机性的来源。但后来有人不熟悉该代码运行 Valgrind,它报告了“问题”。然后修复了“错误”,导致随机数生成器中断。您可以找到更多详细信息here

【讨论】:

  • @g24l 本地变量 - 它们保留在堆栈中。
  • @Kenney 是的,当然它们没有初始化,但是读取初始化的本地(非指针类型)不会导致核心转储,对吧?
  • 在这种情况下,它应该使用单词指针螺母只是变量(或局部变量)。
  • @g24l 读取未初始化的变量可能不会导致核心转储,尽管取消引用未初始化的指针变量可能会这样做。
  • 未初始化变量的内容是indeterminate。你可以用它们做一些事情(包括阅读,在某些情况下,如果你小心的话,甚至可以输出)而不会导致 UB。
猜你喜欢
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2015-04-28
  • 1970-01-01
  • 2017-08-26
  • 2012-12-19
  • 1970-01-01
  • 2013-07-24
相关资源
最近更新 更多