C标准保证这size_t是一种可以保存任何数组索引的类型.这意味着,逻辑上,size_t应该能够保存任何指针类型.我在Googles上发现的一些网站上看到这是合法的和/或应该始终有效:
void *v = malloc(10);
size_t s = (size_t) v;
Run Code Online (Sandbox Code Playgroud)
那么在C99中,标准引入了intptr_t和uintptr_t类型,它们是有符号和无符号类型,保证能够保存指针:
uintptr_t p = (size_t) v;
Run Code Online (Sandbox Code Playgroud)
那么使用size_t和有uintptr_t什么区别?两者都是无符号的,并且两者都应该能够保存任何指针类型,因此它们在功能上看起来相同.除了清晰度之外,是否有任何真正令人信服的理由uintptr_t(或者更好的是,a void *)而不是a size_t?在一个不透明的结构中,字段只能由内部函数处理,有没有理由不这样做?
出于同样的原因,ptrdiff_t一直是一个能够保持指针差异的签名类型,因此能够容纳大多数指针,那么它与它intptr_t有何区别?
是不是所有这些类型基本上都服务于同一功能的不同版本?如果没有,为什么?对于其中一个我不能用另一个做什么我不能做什么?如果是这样,为什么C99会在语言中添加两种基本上多余的类型?
我愿意忽略功能指针,因为它们不适用于当前的问题,但随意提及它们,因为我有一种潜在的怀疑,它们将成为"正确"答案的核心.
将指针转换为int并稍后再返回指针是否安全?
如果我们知道指针是否为32位长且int是32位长怎么样?
long* juggle(long* p) {
static_assert(sizeof(long*) == sizeof(int));
int v = reinterpret_cast<int>(p); // or if sizeof(*)==8 choose long here
do_some_math(v); // prevent compiler from optimizing
return reinterpret_cast<long*>(v);
}
int main() {
long* stuff = new long(42);
long* ffuts = juggle(stuff);
std::cout << "Is this always 42? " << *ffuts << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这是否包含在标准中?
我想为我的自定义类型AnimationSet重载std :: hash模板:
struct AnimationSet {
const AnimationData *animationData;
SceneNode *sceneNode;
bool operator==(const AnimationSet &other) const {
return ( this->animationData == other.animationData &&
this->sceneNode == other.sceneNode );
}
};
Run Code Online (Sandbox Code Playgroud)
如您所见,它是一个只包含两个指针的结构.
将这些指针强制转换为unsigned int以计算AnimationSet的哈希值是否合法?
namespace std {
template<>
struct hash<AnimationSet> {
size_t operator()(const AnimationSet &set) const {
hash<unsigned int> h;
return h((unsigned int)set.animationData) ^ h((unsigned int)set.sceneNode);
}
};
}
Run Code Online (Sandbox Code Playgroud)
编辑:我在哈希重载的上下文中问这个问题,但我想知道更一般的问题的答案:"将任何指针转换为unsigned int是否公平?"