我有一个结构
struct detail { int id; uintptr_t init; // blah blah }; struct detail info; info.id = 1; info.init = (uintptr_t)NULL;
我必须使init
成员为NULL。 如果我强制转换(或不强制转换) NULL
可能会发生什么? 如果我直接将它赋值为NULL,如info.init = NULL;
它在运行时错误方面有什么不同吗? 它编译好。 但是代码的执行是我最关心的问题。
谢谢
标准中没有保证,如果ptr
是一个空指针,那么(uintptr_t)ptr
是0
。
如果你不关心空指针和零整数不等价的系统,那么info.init = 0;
很好。
init
成员有整数类型,不能被“空”。 你可以给它赋值0
,或者你可以赋给它一个空指针转换为uintptr_t
。 几乎所有的C实现都是一样的。 但是不能保证,而且有一些系统是不一样的。
NULL
可能是一个空指针,或者它可能是一个整数常量0
。 在后一种情况下,标准中保证(uintptr_t)(NULL)
为0
。 所以可以有info.init = NULL; (void*)(info.init);
info.init = NULL; (void*)(info.init);
有未定义的行为。 如果null的整数不等于0,则不会产生空指针,计算无效的指针值为UB。
所以,如果你想保证这个info
,当转换为一个指针类型,产生一个空指针,然后为了真正的可移植性,你应该做info.init = (uintptr_t)(void*)(NULL);
。 你可以选择给读者提供一个额外的线索,包括uintptr_t
将要被转换的指针类型,而不是void*
。 存储uintptr_t
原因很少,所以提示可能会对读者有所帮助。
请注意,在标准中保证一个零值常量表达式转换为指针类型,是一个空指针。 这并不意味着转换为指针类型的零值非常量表达式是空指针。 这也不意味着一个空指针,转换为整数类型,为0.在大多数实现(包括所有“现代”)中,最后两件事是正确的。
NULL是一个内置常量,其值与系统中的空指针相匹配。 将常数值赋予与系统上的指针相同的大小(或更大)的int是完全有效的。
我会投这里投,因为分配指向整数的指针通常是不允许的,并会产生一个警告。 当然,使用intptr_t
是个好主意,因为它足够大。