我很难理解 C 中严格别名的一个方面。
据我了解,不兼容类型的指针不能相互转换。但是,在将这些不同类型转换为
void*
或 char*
,甚至转换为它们的数字表示形式之后,如何比较这些不同类型之间的指针比较呢?
在 C 中,(比方说 C23)以下断言得到保证吗?
int x = 1;
float y = 1.0f;
assert((void*)(&x) != (void*)(&y)); // always passes?
assert((char*)(&x) != (char*)(&y)); // always passes?
// something like a "reinterpret cast" to uint64_t
// or another type that is correct for some system
assert((uint64_t)(&x) != (uint64_t)(&y)); // always passes?
我为什么问:这两个变量的位置是否允许在数值上(或其他方面)相等?例如,浮点数可能存储在某种“浮点内存”中,而 int 可能存储在某些具有相同地址的“整型内存”中,但 CPU 根据类型查找 int 内存或浮点内存?
我很好奇的是,是否可以有两个不同的堆栈,例如针对不同的数据类型(假设的示例:将浮点数存储在 GPU 内存中,将整数存储在普通内存中,或者类似的东西,但是地址比较相等)那个硬件)。或者编译器是否需要将这些差异带回到比较运算符中?
我对此的发现:
我尝试过的:我试图让断言失败,但它们每次都有效,但我很好奇如果符合标准的编译器做了一些特殊的事情,理论上它们是否会失败
基本上,对于不兼容数据类型的指针,比较是否有意义?如果不是,尽管变量不同,它是否可以“相等”?
断言总是会通过,因为你有两个变量在内存中分配了空间,它们都从尚未分配的空间中分配空间,并且当内存中的空间被分配时
y
,x
已经占据了自己的位置。
但是,不同类型的两个不同变量可以具有相同的地址,因此可能有两个不同类型的不同指针引用相同的地址。
证明:
#include <stdio.h>
int main() {
int someint = 123;
int *a = &someint;
float *b = (float *)a;
printf("a is located at %p, b is located at %p", a, b);
return 0;
}