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地址(因此全0
uintpttr\t
)。在上个世纪,出现了一些奇怪、不寻常的例外(但当时不存在)。并且类型转换不会更改为相同大小的源和目标生成的机器代码[浮点除外]。英特尔奔腾双核/编译时使用VS2010@BasileStarynkevitch你的意思是说使用
info.init=(uintpttr_t)NULL
info.init=NULL
不会有什么不同是的,那不会有什么不同,你最好将code
info.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指针常量。