空指针是如何实现的?
How are void pointers implemented?
我想知道 void 指针是如何实现的。我试图用 x86-64 在 Godbolt 上找到它(你可以看到它 here),但它没有显示任何内容。 void指针是如何实现的?
编辑:
这是我使用的代码:
int main() {
int volatile y = 123;
void* volatile x = &y;
}
我想在这里看到的只是 x
的样子。我放置了 volatile 以便 gcc 不会将其作为死代码消除。
一般来说,x86-64 处理器上的所有指针都只是包含一些内存地址的 8 字节值。只有编译器关心它们指向它的内容。
从我的角度来看,asm 清楚地揭示了 void*
使用与其他指针相同的对象表示,例如 int*
,因此向 void*
和从 void*
进行转换是不行的-op 只是让编译器的类型系统开心。
asm 中的所有内容都只是字节,您可以根据需要对其进行整数运算。 指针只是您可以取消引用的整数。例如在 x86-64 asm 中,+1
到 uintptr_t
与 +1
到 char*
没有区别,因为 C 将 sizeof(char)
定义为 1
, x86-64 是字节可寻址的,因此指针的每个整数增量都是一个新字节。 (所以 x86-64 上的 C 实现使用 CHAR_BIT=8)。
void*
只是一种可以保存任何指针值的类型,但不允许您使用 +1
或其他任何方法对其进行数学运算。 C 中的 OTOH 你不需要强制转换以分配其他指针类型 to/from 它。
所有这些都来自具有平面内存模型的 x86-64,而不是 seg:off 之类的东西。并且函数指针与数据指针具有相同的表示。在假设的机器(或 C 实现)上,您可能会看到 void*
.
的一些特殊内容
例如在字可寻址内存之上模拟 CHAR_BIT=8 的机器可能具有 sizeof(char*) > sizeof(int*)
,但 void*
必须足够宽以容纳任何可能的指针,甚至可能具有不同的格式比任何一个。 (有一个窄的 char
实际上不能以线程安全的方式存储(没有包含词的非原子 RMW)对于 C11 是不可行的。)
半相关: 谈论 C 指针如何在其他假设的非简单实现中工作。 seg:off 指针模型不会使 void*
不同于 int*
。
加上上面的答案,内存没有任何类型。一般而言,每个指针类型基本上都是一个无符号长整型值,指向内存中的某个地址。
本来C语言没有void*
,char*
是泛型指针类型。引用 C: A Reference Manual:
the problem with this use of char*
is that the compiler cannot check that
programmers always convert the pointer type properly
我想知道 void 指针是如何实现的。我试图用 x86-64 在 Godbolt 上找到它(你可以看到它 here),但它没有显示任何内容。 void指针是如何实现的?
编辑: 这是我使用的代码:
int main() {
int volatile y = 123;
void* volatile x = &y;
}
我想在这里看到的只是 x
的样子。我放置了 volatile 以便 gcc 不会将其作为死代码消除。
一般来说,x86-64 处理器上的所有指针都只是包含一些内存地址的 8 字节值。只有编译器关心它们指向它的内容。
从我的角度来看,asm 清楚地揭示了 void*
使用与其他指针相同的对象表示,例如 int*
,因此向 void*
和从 void*
进行转换是不行的-op 只是让编译器的类型系统开心。
asm 中的所有内容都只是字节,您可以根据需要对其进行整数运算。 指针只是您可以取消引用的整数。例如在 x86-64 asm 中,+1
到 uintptr_t
与 +1
到 char*
没有区别,因为 C 将 sizeof(char)
定义为 1
, x86-64 是字节可寻址的,因此指针的每个整数增量都是一个新字节。 (所以 x86-64 上的 C 实现使用 CHAR_BIT=8)。
void*
只是一种可以保存任何指针值的类型,但不允许您使用 +1
或其他任何方法对其进行数学运算。 C 中的 OTOH 你不需要强制转换以分配其他指针类型 to/from 它。
所有这些都来自具有平面内存模型的 x86-64,而不是 seg:off 之类的东西。并且函数指针与数据指针具有相同的表示。在假设的机器(或 C 实现)上,您可能会看到 void*
.
例如在字可寻址内存之上模拟 CHAR_BIT=8 的机器可能具有 sizeof(char*) > sizeof(int*)
,但 void*
必须足够宽以容纳任何可能的指针,甚至可能具有不同的格式比任何一个。 (有一个窄的 char
实际上不能以线程安全的方式存储(没有包含词的非原子 RMW)对于 C11 是不可行的。)
半相关:void*
不同于 int*
。
加上上面的答案,内存没有任何类型。一般而言,每个指针类型基本上都是一个无符号长整型值,指向内存中的某个地址。
本来C语言没有void*
,char*
是泛型指针类型。引用 C: A Reference Manual:
the problem with this use of
char*
is that the compiler cannot check that programmers always convert the pointer type properly