【问题标题】:Another C pointer Question另一个 C 指针问题
【发布时间】:2009-07-11 14:28:22
【问题描述】:

以下代码:

int *a;
*a = 5;

很可能会导致分段错误,我知道原因。

以下代码:

int a;
*a = 5;

甚至不会编译。 (gcc 说:一元 * 的类型参数无效)。

现在,指针只是一个整数,用于 用于存储地址。 那么,如果我说,为什么会有问题:

*a = 5;

理想情况下,这也应该导致分段错误。

【问题讨论】:

  • 指针是无符号序数标量,不一定是整数。
  • 值得注意的是,为了一致性/清晰起见,预期分段错误并不是考虑此类情况下行为的一种过于准确的方法。取消引用任意内存地址在 C 中是未定义的行为。在许多情况下,它会产生分段错误,但这不是必需的。它可能会引发总线错误(Mac OS X 喜欢这样做)。如果它恰好是有效的,它可能会给你该地址的内容。
  • 虽然C 难以检测未正确初始化的指针,但它没有检测到int 数据类型取消引用。它会在编译时阻止你。但是,您可以使用 *(unsigned int *)a = 5 强制它,并且可能会得到您期望的分段错误。我说“可能”是因为a 的值很可能会转换为程序上下文中的可寻址位置——你会错过你的错误,但会遇到随机寻址的细微错误。
  • 如果你把指针算作整数,那么一切都只是整数。毕竟,二进制数字计算机只存储 1 和 0。在 C 编程语言的抽象级别,指针存储的是内存地址,而不是整数。

标签: c pointers


【解决方案1】:

指针不是整数。 C 有数据类型来

a) 防止某些编程错误,并且

b) 提高​​程序的可移植性

在某些系统上,指针可能不是整数,因为它们实际上由两个整数(段和偏移量)组成。在其他系统上,“int”类型不能用于表示指针,因为 int 是 32 位,而指针是 64 位。由于这些原因,C 不允许将整数直接用作指针。如果要使用大到足以容纳指针的整数类型,请使用 intptr_t。

【讨论】:

    【解决方案2】:

    当你说

    int a;
    *a = 5;
    

    你试图让编译器取消引用不是指针的东西。当然,您可以将其强制转换为指针,然后取消引用它,就像这样,

    *((int*)a) = 5;
    

    .. 这告诉编译器你真的非常想这样做。但是——这是一种冒险的事情。为什么?好吧,例如,在您的示例中,您实际上从未初始化过 a 的值,因此当您将其用作指针时,您将在用于 a 的位置处获得任何值。由于它看起来像是一个局部变量,因此它将是函数堆栈框架中未初始化的位置,并且可以是任何东西。本质上,您会尝试将值 5 写入某个未确定的位置;真的不是明智之举!

    【讨论】:

      【解决方案3】:

      据说是为了说明指针只存储地址,地址可以被认为是数字,很像整数。但通常地址具有结构(如页码、页内偏移量等)。

      你不应该一言以蔽之。整数字面上存储一个数字,您可以对其进行加、减等操作。但您不能将其用作指针。整数就是整数,指针就是指针。它们服务于不同的目的。

      有时,从指针到整数的转换可能是必要的(无论出于何种目的 - 可能在操作系统内核中进行一些地址运算)。然后您可以将指针转换为这样的整数类型,之前确定您的编译器是否保证正确的大小并保留值。但是如果你想取消引用,你必须转换回指针类型。

      【讨论】:

        【解决方案4】:

        在第一种情况下,您永远不会真正分配“a”。

        int* a = ?
        *a = 5; //BAD. What is 'a' exactly?
        
        int a = ? //but some int anyway
        *a = 5; //'a' is not a pointer!
        

        如果您希望将整数用作指针,则必须先转换它。指针可能整数,但从概念上讲,它们有不同的用途。

        【讨论】:

          【解决方案5】:

          运算符* 是一个未为整数数据类型定义的一元运算符。这就是为什么声明

          *a = 5;

          不会编译。

          另外,整数和指针不是一回事。它们在内存中的大小通常相同(32 位系统为 4 字节)。

          【讨论】:

            【解决方案6】:

            int* a — 是一个指向 int 的指针。它没有指向任何地方,你还没有初始化它。请在提出此类问题之前阅读任何有关 C 的书籍。

            【讨论】:

            • 我明确写过我知道它为什么会失败...我的问题是为什么第二个 sn-p 不能编译?
            • 一点点上课将大大有助于避免对您的答案多次投反对票。
            猜你喜欢
            • 1970-01-01
            • 2010-11-15
            • 2011-08-02
            • 2011-04-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多