指针(地址)可以是负数吗?

Jar*_*yth 35 c signed pointers return-value

我有一个函数,我希望能够返回失败未初始化的特殊值(它返回成功指针).

目前它为失败返回NULL,为未初始化返回-1,这似乎有效......但我可能会欺骗系统.iirc,地址总是积极的,不是吗?(虽然由于编译器允许我将地址设置为-1,这看起来很奇怪).

[更新] 我有另一个想法(如果-1是有风险的)是malloc一个char @全局范围,并使用该地址作为哨兵.

caf*_*caf 71

不,地址并不总是正的 - 在x86_64上,指针是符号扩展的,地址空间对称地聚集在0左右(尽管通常"负"地址是内核地址).

然而,这一点大多没有实际意义,因为C只定义了指向同一个对象的一部分或一个超过数组末尾的指针之间的含义<>指针比较.指向完全不同的对象的指针除了完全相等之外不能进行有意义的比较,至少在标准C if (p < NULL)中没有明确定义的语义.

您应该创建一个具有静态存储持续时间的虚拟对象,并使用其地址作为您的unintialised值:

extern char uninit_sentinel;
#define UNINITIALISED ((void *)&uninit_sentinel)
Run Code Online (Sandbox Code Playgroud)

它保证在您的程序中有一个唯一的地址.

  • @mfukar:我个人认为ABI架构比维基百科更具权威性.最后,正如我相信你知道的那样,无论如何,这最终都是解释问题或者你如何构思地址空间. (5认同)
  • "地址空间的负半部分"是指System V OS规范的x64变体将位模式解释为有符号值,因此仅适用于选择进行该解释的环境.可以很容易地写出'msb set'的地址.Windows采用无符号解释,并将此类地址称为高地址空间.x64指令集中没有任何内容暗示该值应该以某种方式解释,尽管我见过的大多数OS都使用无符号 - +1用于查找带符号的指针环境 (2认同)

Jam*_*lis 20

指针的有效值完全取决于实现,因此,是的,指针地址可能是负数.

但是,更重要的是,考虑(作为可能的实现选择的示例)您使用32位指针大小的32位平台的情况.可以由该32位值表示的任何值都可以是有效指针.除了空指针之外,任何指针值都可能是指向对象的有效指针.

对于您的特定用例,您应该考虑返回状态代码,并可能将指针作为函数的参数.

  • 但是要小心,如果你的指针过于负面,它可能最终会在你当前的机器旁边贴上机器. (42认同)

Jar*_*ger 17

尝试将特殊值复用到返回值上通常是一个糟糕的设计......你试图用单个值做太多.通过参数而不是返回值返回"成功指针"会更清晰.这会在您要描述的所有条件的返回值中留下大量非冲突空格:

int SomeFunction(SomeType **p)
{
    *p = NULL;
    if (/* check for uninitialized ... */)
        return UNINITIALIZED;
    if (/* check for failure ... */)
        return FAILURE;

    *p = yourValue;
    return SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

您还应该进行典型的参数检查(确保'p'不是NULL).

  • 这绝对是设计此功能的正确方法.对于使用该代码的任何其他人来说,任何其他事情都将是一次维护灾难和错误磁铁,应该强烈反对. (6认同)
  • 有可能."发明"无效指针的人说这是一个错误,IIRC.另一个特例值可能是个问题.即便如此,有时使用两个单独的值会导致代码过复杂.*简化*一些常用算法的常用方法是分配特殊情况的过去对象,例如,而不是使用空值 - 它避免了特殊情况的空检查.拥有"有效"标志仍然需要那些在端检查,只是以不同的形式.指向特殊对象*的有效指针是*特殊情况指针,通常可以节省大量复杂性. (2认同)
  • "那家伙"是CAR Hoare.另一方面,他通过Quicksort的发明弥补了"十亿美元的错误":-) (2认同)
  • @James - 所有这些人,他们只是男人,你知道吗?我可能*应该*记住Hoare,但是*who*只是历史.这些想法更重要.此外,我觉得模糊是有帮助的 - 当人们不知道我在引用谁时,人们很难与我发生矛盾;-) (2认同)

AnT*_*AnT 5

C语言没有为指针定义"否定性"的概念."否定"的属性主要是算术的,不以任何方式适用于指针类型的值.

如果你有一个指针返回函数,那么你无法有意义地返回该-1函数的值.在C语言中,积分值(除零之外)不能隐式转换为指针类型.尝试-1从指针返回函数返回是立即约束违规,将导致诊断消息.简而言之,这是一个错误.如果您的编译器允许它,它只是意味着它不会过于严格地强制执行该约束(大多数时候它们是为了与预标准代码兼容).

如果-1通过显式强制转换强制指针类型的值,则强制转换的结果将是实现定义的.语言本身并不能保证它.它可能很容易证明与其他一些有效的指针值相同.

如果要创建保留指针值,则无需malloc任何操作.您可以简单地声明所需类型的全局变量,并使用其地址作为保留值.它保证是独一无二的.