Lun*_*din 10 c nullptr language-lawyer type-punning c23
考虑这个联盟:
\ntypedef union\n{\n void* vptr;\n nullptr_t nptr;\n} pun_intended;\nRun Code Online (Sandbox Code Playgroud)\nnullptr_t据说与void* 1)兼容。好吧,如果我们将 初始化void*为某个非零值怎么办?
pun_intended foo = { .vptr = (void*)42 }; \nRun Code Online (Sandbox Code Playgroud)\nnullptr_t引入之前是合法的。完整示例:
\n#include <stdio.h>\n#include <inttypes.h>\n#include <stddef.h>\n\ntypedef union\n{\n void* vptr;\n nullptr_t nptr; \n} pun_intended;\n\nint main(void)\n{\n pun_intended foo = { .vptr = (void*)42 };\n printf("Value: %" PRIuPTR "\\n", (uintptr_t)foo.vptr);\n\n if(foo.nptr != (void*)42)\n {\n puts("It does not have value 42.");\n if(foo.nptr == nullptr) \n puts("Because it's a nullptr.");\n else\n puts("But it's not a nullptr.");\n\n unsigned int val = *(unsigned char*)&foo; // little endian assumption here\n printf("And it has value %d.\\n", val);\n\n if(foo.vptr != nullptr)\n {\n puts("foo.vptr is however not a nullptr.");\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nclang 16 -std=c2x 上的输出:
\nValue: 42\nIt does not have value 42\nBecause it's a nullptr\nAnd it has value 42.\nfoo.vptr is however not a nullptr\nRun Code Online (Sandbox Code Playgroud)\ngcc 13.2 -std=c2x 上的输出:
\nValue: 42\nIt does not have value 42.\nBut it's not a nullptr.\nAnd it has value 42.\nfoo.vptr is however not a nullptr.\nRun Code Online (Sandbox Code Playgroud)\n我的问题:以上任何内容(以前是明确定义的或 impl.define 的)现在是未定义/未指定的行为吗?如果有的话,哪里有说明?或者 C23 中根本没有考虑这些场景 - 一个缺陷?
\n1)来源:C23 n3096 草案 7.21.2
\n\n\n的大小和对齐方式
\nnullptr_t与指向字符类型的指针相同。该值的对象表示形式nullptr与 类型的空指针值的对象表示形式相同void*。
\n\n好吧,如果我们将 初始化
\nvoid*为某个非零值怎么办?
C 2023 N3096 7.21.2 3 明确回答了这个问题。nullptr在告诉我们类型中值的表示nullptr_t与类型中空指针值的表示相同之后void *,它告诉我们如果对象中存在不同的字节值序列会发生什么nullptr_t:
\n\n\xe2\x80\xa6 如果对象表示不同,则行为未定义。
\n