将指针与负值进行比较

时间:2013-10-02 14:22:49

标签: c pointers data-structures compiler-construction

我可以将指向结构的指针强制转换为有符号值,以返回不同类型的错误。 C标准是允许这个还是未定义的行为。

typedef enum lError
{
  l_OK = 0,
  l_ERROR = -1,
  l_ABORT = -2,
  l_HALT = -3
}L_STATUS;


typedef struct dataCards
{
  int card1;
  int card2;
  char flag;
}DATACARD;

DATACARD dataCardG;

DATACARD *getCard(int i)
{
  if(i == 1)
    return &dataCardG;
  else if (i == 2)
    return (DATACARD *)l_ERROR;
  else if (i==3)
    return (DATACARD *)l_ABORT;
  else
   return (DATACARD *)l_HALT;

}

int main ()
{
  DATACARD *ptr = NULL;

  ptr = getCard(3);
  if(ptr < (DATACARD *) 1)   /* Is this allowed or undefined behaviour */
    printf("Card failed\n");

}

我如何使这个条件有效?

3 个答案:

答案 0 :(得分:4)

C标准“允许”这个,但它不支持它。也就是说,它不会定义尝试此操作时发生的行为。您的C实现也可能无法定义尝试此操作时发生的行为。

不要这样做。

您可以通过创建实际对象来合法地完成此工作:

DATACARD okay, error, abort, halt

#define Okay  (&okay)
#define Error (&error)
#define Abort (&abort)
#define Halt  (&halt)

如果DATACARD更大并且您不想浪费这些额外对象的空间,则还有其他可用技术。通常,类似getCard的例程将被定义为在出现错误时返回NULL并通过单独的机制提供错误代码,例如指向存储错误代码的位置的附加参数。

答案 1 :(得分:3)

UNIX sbrk()函数依赖于此工作,因为它返回-1作为指针值以指示特定情况。因此,虽然C标准并不能保证它能够正常工作......但它仍然有用。

但是,为了比较这些值,总是将指针强制转换为整数类型,而不是相反。这将避免64位系统上的位宽问题,并确保您在签名的上下文中执行操作。

答案 2 :(得分:0)

这是未定义的行为

规范(下面)有点长,但关键是getCard()返回(DATACARD *) some_int之类的值。它不是some_int可能是负数,它可以是0以外的任何整数,但仍然存在问题。由于返回值可能不是基于类型(DATACARD *)的实际现有变量而不是NULL,因此任何此类比较都是未定义的。

推荐使用@Eric Postpischil:

DATACARD okay, ...
#define Okay  (&okay)

此外,(DATACARD *) -1不一定是“否定”指针。我发现没有C规范可以确认指针是否有签名,无符号或任何一个。 (规范可能存在。)-1肯定是否定的,但这种派生指针的符号并不确定。

C11dr 6.5.8 5“当比较两个指针时,结果取决于指向的对象的地址空间中的相对位置。如果指向对象类型的两个指针都指向相同 object,..或如果指向的对象是相同聚合对象的成员,...在所有其他情况下,行为未定义。“