考虑一下这个联盟:
typedef union
{
void* vptr;
nullptr_t nptr;
} pun_intended;
nullptr_t
应该与void*
1)兼容.好的,那么如果我们将void*
初始化为某个非零值呢?
pun_intended foo = { .vptr = (void*)42 };
- 根据C23 6.3.2.3第4节,此转换被认为是合法的(隐含定义的),或者至少在引入
nullptr_t
之前是合法的. - 那么unions 式的双关语呢?同样被认为是合法的.
- 如何使用字符类型指针判断C中任何类型的内部表示形式,该指针在C23,6.3.2.3§7之前定义得很好.
完整示例:
#include <stdio.h>
#include <inttypes.h>
#include <stddef.h>
typedef union
{
void* vptr;
nullptr_t nptr;
} pun_intended;
int main(void)
{
pun_intended foo = { .vptr = (void*)42 };
printf("Value: %" PRIuPTR "\n", (uintptr_t)foo.vptr);
if(foo.nptr != (void*)42)
{
puts("It does not have value 42.");
if(foo.nptr == nullptr)
puts("Because it's a nullptr.");
else
puts("But it's not a nullptr.");
unsigned int val = *(unsigned char*)&foo; // little endian assumption here
printf("And it has value %d.\n", val);
if(foo.vptr != nullptr)
{
puts("foo.vptr is however not a nullptr.");
}
}
}
CLANG 16-STD=c2x上的输出:
Value: 42
It does not have value 42
Because it's a nullptr
And it has value 42.
foo.vptr is however not a nullptr
GCC 13.2-std=c2x上的输出:
Value: 42
It does not have value 42.
But it's not a nullptr.
And it has value 42.
foo.vptr is however not a nullptr.
我的问题是:以上这些(以前是明确定义的或隐含的)现在有没有什么行为是未定义/未规定的?如果是,这是在哪里陈述的?或者这些场景根本没有在C23中被考虑--这是一个缺陷?
1)来源:C23 n3096草案7.21.2
nullptr_t
的大小和对齐方式与指向字符类型的指针相同.值nullptr
的对象表示与类型void*
的空指针值的对象表示相同.