我可以将指向结构的指针强制转换为有符号值,以返回不同类型的错误。 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");
}
我如何使这个条件有效?
答案 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,..或如果指向的对象是相同聚合对象的成员,...在所有其他情况下,行为未定义。“