C语言中的类型转换空指针
我有一个结构C语言中的类型转换空指针,c,windows,struct,null,C,Windows,Struct,Null,我有一个结构 struct detail { int id; uintptr_t init; // blah blah }; struct detail info; info.id = 1; info.init = (uintptr_t)NULL; 我必须使init成员为空。如果我使用typecast(或不使用typecast)NULL,会发生什么情况?如果我直接将其赋值为NULL,比如info.init=NULL它对运行时错误有什么影响吗。它编译得很好。但是代码的执行是我最关心的 感谢NUL
struct detail {
int id;
uintptr_t init;
// blah blah
};
struct detail info;
info.id = 1;
info.init = (uintptr_t)NULL;
我必须使init
成员为空。如果我使用typecast(或不使用typecast)NULL
,会发生什么情况?如果我直接将其赋值为NULL,比如info.init=NULL代码>它对运行时错误有什么影响吗。它编译得很好。但是代码的执行是我最关心的
感谢NULL是一个内置常量,其值与系统上的任何NULL指针相匹配。将常量值指定给与系统上的指针大小相同(或更大)的int是完全有效的。标准中没有保证如果ptr
是空指针,那么(uintpttr\t)ptr
就是0
如果您不关心空指针和零整数不相等的系统,那么info.init=0代码>很好
init
成员具有整数类型,不能“设为null”。您可以将0
分配给它,也可以将空指针转换为uintpttr\t
的结果分配给它。在几乎所有的C实现中,这些都是一样的。但这并没有得到保证,而且有些系统的情况也不尽相同
NULL
可能是空指针,也可能是整数常量0
。在后一种情况下,标准中保证(uintpttr\t)(NULL)
为0
。因此可能存在info.init=NULL的实现;(void*)(info.init)代码>具有未定义的行为。如果null的等效整数不是0,并且计算无效指针值是UB,则不会产生null指针
因此,如果您想保证info
,当转换为指针类型时,会产生空指针,那么为了实现真正的可移植性,您应该执行info.init=(uintpttr_t)(void*)(null)代码>。您可以选择通过包含uintptr\u t
将要转换为的指针类型,而不是void*
来为读者提供额外的线索。存储uintptr\u t
的理由很少,因此提示正在发生的事情可能会对读者有所帮助
请注意,标准中有一个保证,即转换为指针类型的零值常量表达式是空指针。这并不意味着转换为指针类型的零值非常量表达式是空指针。这也不意味着转换为整数类型的空指针是0。最后两件事在大多数实现(包括所有“现代”实现)中都是正确的。我在这里投票赞成强制转换,因为通常不允许将指针指定给整数,并且会生成警告。当然,使用intptr\t
是一个非常好的主意,因为它足够大。您忘了提到您的目标操作系统和处理器。您可以编写info.init=0代码>几乎总是相同的。当前系统几乎总是将NULL
指针表示为全0地址(因此全0uintpttr\t
)。在上个世纪,出现了一些奇怪、不寻常的例外(但当时不存在)。并且类型转换不会更改为相同大小的源和目标生成的机器代码[浮点除外]。英特尔奔腾双核/编译时使用VS2010@BasileStarynkevitch你的意思是说使用info.init=(uintpttr_t)NULL
或info.init=NULL
不会有什么不同是的,那不会有什么不同,你最好将codeinfo.init=0
几乎每个系统都有一个NULL
指针,它是一个所有位都已清除的字(但C标准的措辞允许非常罕见的系统,在这些系统上,这可能是错误的;我今天无法说出任何相关的系统;但在上个世纪,我从未见过非常奇怪的系统,这种情况确实发生过……)@请不要混淆内存中的空表示和代码中的表示。NULL
指针的表示形式可能是0xdeadbeef
,但这只意味着编译器需要进行翻译,以便指针上下文中的0
在写入时变为0xdeadbeef
,反之亦然。为了清晰起见,我建议使用NULL
,这是C中的标准。在理论上是一致的,但在实践中不是。我认为,对于NULL
不是0,而是机器级0xdeadbeef
的硬件,很难编写一个符合标准C99的实际大小的程序。(而且编译器可能也会有bug!)没有uintpttr\u t
是某种整数类型(你可以将它乘以某个小常数)@BasileStarynkevitch:编写程序或编译器都不是人类的智慧所能超越的。对于该程序,必须避免使用memset
初始化指针数据等错误。对于编译器,当常量整数表达式转换为指针类型时,您可能需要一个特殊情况。@SteveJessop:我很困惑;你是对的。谢谢你的更正。@BasileStarynkevitch:当然,我的回答中的“如果你不在乎……”涵盖了这个练习。在C99中,NULL
是在stddef.h
中定义为空指针的宏;在Visual Studio中,它是一个定义为0的宏。在这两种情况下,它都不是内置常量。-1这是不正确的NULL
是一个宏,必须定义为0
(或到(void*)0
),编译器将指针上下文中的0
转换为NULL指针常量。