C99中固定大小的指针类型
我想创建一个类型来存储指针。该类型应与C99兼容,并具有64位的固定宽度。我提出了几个备选方案,但它们似乎都有缺陷:C99中固定大小的指针类型,c,pointers,portability,c99,C,Pointers,Portability,C99,我想创建一个类型来存储指针。该类型应与C99兼容,并具有64位的固定宽度。我提出了几个备选方案,但它们似乎都有缺陷: 使用uint64\u t是不正确的,因为指针和整数之间的转换是实现定义的[,6.3.2.3] uinptr_t也似乎不在图片范围内,因为这种类型的宽度不是固定的,而且类型是可选的[7.18.1.4] 使用结构,例如 struct { #ifdef __LP64__ void* ptr; #else // if big endian the followi
- 使用
是不正确的,因为指针和整数之间的转换是实现定义的[,6.3.2.3]李>uint64\u t
也似乎不在图片范围内,因为这种类型的宽度不是固定的,而且类型是可选的[7.18.1.4]李>uinptr_t
- 使用结构,例如
也不起作用,因为指针的大小不是固定的struct { #ifdef __LP64__ void* ptr; #else // if big endian the following two fields need to be flipped void* ptr; uint32_t padding; #endif } fixed_ptr_type;
void*
。任何对象指针都可以转换为void*
,然后再转换回来
函数指针
void*
不一定存储函数指针。但是,任何函数指针都可以转换为另一种类型的函数指针,因此可以将它们存储在任意类型中(例如void(*)(void)
)
衬料
我不知道为什么您需要指针类型具有预定的大小,但您可以使用并集填充它们,并希望结果不会太大:
union fixed_ptr_type {
void *p;
char c[64/CHAR_BIT];
};
assert (CHAR_BIT * sizeof (union fixed_ptr_type) == 64);
对象指针
存储对象指针的最佳类型是void*
。任何对象指针都可以转换为void*
,然后再转换回来
函数指针
void*
不一定存储函数指针。但是,任何函数指针都可以转换为另一种类型的函数指针,因此可以将它们存储在任意类型中(例如void(*)(void)
)
衬料
我不知道为什么您需要指针类型具有预定的大小,但您可以使用并集填充它们,并希望结果不会太大:
union fixed_ptr_type {
void *p;
char c[64/CHAR_BIT];
};
assert (CHAR_BIT * sizeof (union fixed_ptr_type) == 64);
我不理解你反对使用带有填充的
void*
。同一类型的所有对象具有相同的大小。如果不同的对象指针类型具有不同的大小,这无关紧要,因为您可以将其转换为void*
以将其存储在超级指针中
关于uintpttr\u t
:如果不支持它,那么很可能是因为在特定平台上实际上没有办法做到这一点
因此您可以使用
uintptr\t
。要添加固定宽度要求,您可以先转换到uintpttr\t
,然后再转换到uint64\t
(如果您高兴地知道,当有人推出指针大于64位的系统时,您必须更改代码!)我不理解您反对使用带填充的void*
。同一类型的所有对象具有相同的大小。如果不同的对象指针类型具有不同的大小,这无关紧要,因为您可以将其转换为void*
以将其存储在超级指针中
关于uintpttr\u t
:如果不支持它,那么很可能是因为在特定平台上实际上没有办法做到这一点
因此您可以使用
uintptr\t
。要添加固定宽度要求,您可以转换到uintpttr\t
,然后转换到uint64\t
(如果您很高兴知道当有人推出指针大于64位的系统时,您必须更改代码!)您无法以64位类型便携存储指针值。实现使用128位指针是完全合法的
如果您不介意失去对指针大于64位的系统的可移植性,您可能可以使用
uint64\t
。从指针类型到uint64\u t
的转换不能保证在不丢失信息的情况下正常工作,但在指针宽度不超过64位的任何合理系统上,它们几乎肯定会这样做
如果一个实现没有不带填充位的64位无符号整数类型,那么它将根本不定义uint64\u t
(例如,一个具有9位字节的系统将无法实现uint64\u t
)。有一种类型uint_至少64_t
,顾名思义,它保证至少64位宽;它在大多数系统上正好是64位,并且仅在uint64\t
不存在的系统上才比64位宽
uintptr\u t
保证在不丢失信息的情况下保存转换后的void*
值,但不能保证它存在——如果它不存在,则任何整数类型都不能在不丢失信息的情况下保存转换后的void*
值。一致性实现不需要任何整数类型,它可以保存指针值而不丢失信息
函数指针是另一回事。从函数指针到void*
或任何整数类型的转换具有未定义的行为(因为标准没有说明行为应该是什么)
根本没有一种100%可移植的方式来做你想做的事情。你只需要满足于99.9%的可移植性。如果您不关心函数指针,我建议使用
uint64\u t
(可能定义您自己的typedef
,以明确您在做什么),并添加编译时或运行时检查,以确认sizeof(void*)无法以64位类型移植存储指针值。实现使用128位指针是完全合法的
如果您不介意失去对指针大于64位的系统的可移植性,您可能可以使用uint64\t
。从指针类型到uint64\u t
的转换不能保证在不丢失信息的情况下正常工作,但在指针宽度不超过64位的任何合理系统上,它们几乎肯定会这样做
如果一个实现没有不带填充位的64位无符号整数类型,那么它将