简体   繁体   English

在C中类推NULL指针

[英]Typecasting NULL pointer in C

I have a structure 我有一个结构

struct detail {
int id;
uintptr_t init;
// blah blah
};
struct detail info;
info.id = 1;
info.init = (uintptr_t)NULL;

I have to make the the init member NULL. 我必须使init成员为NULL。 What may/may not happen if I typecast(or do not typecast) NULL ? 如果我强制转换(或不转发) NULL可能/可能不会发生什么? What if I directly assign it NULL like info.init = NULL; 如果我直接将它指定为NULL,如info.init = NULL;info.init = NULL; Does it make any difference with respect to runtime errors. 它是否与运行时错误有任何区别。 It compiles fine. 它汇编得很好。 But the execution of the code is my main concern. 但是代码的执行是我主要关注的问题。

Thanks 谢谢

There is no guarantee in the standard that if ptr is a null pointer, then (uintptr_t)ptr is 0 . 标准中无法保证如果ptr是空指针,则(uintptr_t)ptr0

If you don't care about systems on which null pointers and zero integers aren't equivalent, then info.init = 0; 如果你不关心空指针和零整数不相等的系统,那么info.init = 0; is fine. 很好。

The init member has integer type, it cannot be "made null". init成员具有整数类型,不能为“null”。 You can assign 0 to it, or you can assign to it the result of converting a null pointer to uintptr_t . 您可以为其指定0 ,或者可以为其分配将空指针转换为uintptr_t On almost every C implementation ever, those are the same thing. 在几乎所有的C实现中,这些都是一样的。 But it is not guaranteed, and there have been systems on which it is not the same. 但它并不能保证,并且有一些系统与它不一样。

NULL might be a null pointer, or it might be an integer constant 0 . NULL可能是空指针,也可能是整数常量0 In the latter case, there is a guarantee in the standard that (uintptr_t)(NULL) is 0 . 在后一种情况下, 存在在标准中,一个保证(uintptr_t)(NULL)0 So there can be implementations on which info.init = NULL; (void*)(info.init); 所以可以有info.init = NULL; (void*)(info.init); info.init = NULL; (void*)(info.init); has undefined behavior. 有未定义的行为。 It wouldn't result in a null pointer if the integer equivalent of null isn't 0, and computing an invalid pointer value is UB. 如果null的整数等值不为0,则不会产生空指针,并且计算无效指针值是UB。

So, if you want to guarantee that info , when converted to a pointer type, results in a null pointer then for true portability you should do info.init = (uintptr_t)(void*)(NULL); 所以,如果你想保证info ,当转换为指针类型时,会产生一个空指针然后为了真正的可移植性你应该做info.init = (uintptr_t)(void*)(NULL); . You could optionally give the reader an extra clue by including the pointer type that the uintptr_t is going to be converted to, instead of void* . 您可以通过包含uintptr_t将要转换为的指针类型而不是void*来为读者提供额外的线索。 There are very few good reasons for storing a uintptr_t , so hints what is going on might help the reader. 存储uintptr_t原因很少,因此暗示正在发生的事情可能有助于读者。

Note that there is a guarantee in the standard that a zero-valued constant expression, converted to pointer type, is a null pointer. 请注意,标准中保证转换为指针类型的零值常量表达式是空指针。 This does not imply that a zero-valued non-constant expression, converted to a pointer type, is a null pointer. 并不意味着零值非恒定表达,转换为指针类型,是空指针。 Neither does it imply that a null pointer, converted to integer type, is 0. Those last two things happen to be true in most implementations (including all "modern" ones). 它也不意味着转换为整数类型的空指针为0.最后两件事在大多数实现中都是正确的(包括所有“现代”的)。

NULL is a built in constant with a value matching whatever a null pointer is on your system. NULL是一个内置常量,其值与系统上的空指针无关。 It's perfectly valid to assign the constant value to an int the same size (or bigger) than a pointer on your system. 将常量值分配给与系统上的指针相同大小(或更大)的int是完全有效的。

I would vote for the cast here, since assigning pointers to integers is generally not allowed and will generate a warning. 我会在这里投票,因为通常不允许指定整数指针并且会产生警告。 It's a very good idea to use intptr_t of course, since it's big enough. 当然,使用intptr_t是一个非常好的主意,因为它足够大。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM