简体   繁体   English

void 指针是如何实现的?

[英]How are void pointers implemented?

I was wondering how void pointers are implemented.我想知道如何实现 void 指针。 I tried to find it out on Godbolt with x86-64 (you can see it here ), but it didn't reveal anything.我试图用 x86-64 在 Godbolt 上找到它(你可以在这里看到),但它没有透露任何内容。 How are void pointers implemented? void 指针是如何实现的?

Edit: This is the code I used:编辑:这是我使用的代码:

int main() {
    int volatile y = 123;
    void* volatile x = &y;
}

All I was trying to see here is what x would look like.我想在这里看到的只是x的样子。 I put volatile so that gcc wouldn't eliminate it as dead code.我放了 volatile 以便 gcc 不会将其作为死代码消除。

Generally speaking, all pointers on an x86-64 processor are simply 8 byte values containing some memory address.一般来说,x86-64 处理器上的所有指针都是简单的 8 字节值,其中包含一些 memory 地址。 Only the compiler cares about what they point it.只有编译器关心他们指向什么。

From my perspective, the asm clearly reveals that void* uses the same object-representation as other pointers, such as int* , so casting to and from void* is a no-op that just keeps the compiler's type system happy.从我的角度来看,asm 清楚地表明void*使用与其他指针相同的对象表示,例如int* ,因此转换为 void* 和从void*转换是只保持编译器类型系统满意的无操作。

Everything in asm is just bytes that you can do integer operations on if you want. asm 中的所有内容都只是字节,您可以根据需要对其执行 integer 操作。 Pointers are just integers that you can dereference.指针只是可以取消引用的整数。 eg in x86-64 asm, +1 to a uintptr_t is no different than +1 to a char* , because C defines sizeof(char) as 1 , and x86-64 is byte addressable so every integer increment to a pointer is a new byte.例如,在 x86-64 asm 中,对uintptr_t+1与对char*+1没有什么不同,因为 C 将sizeof(char)定义为1 ,并且 x86-64 是字节可寻址的,因此每个 integer 都是指向新指针的增量字节。 (So C implementations on x86-64 use CHAR_BIT=8). (因此 x86-64 上的 C 实现使用 CHAR_BIT=8)。

void* is just a type you that can hold any pointer value, but that doesn't let you do math on it with +1 or whatever. void*只是一种您可以保存任何指针值的类型,但这不允许您使用+1或其他方式对其进行数学运算。 OTOH in C you don't need to cast to assign other pointer types to/from it. C 中的 OTOH,您无需进行强制转换即可为其分配其他指针类型。


All of this follows from x86-64 having a flat memory model, not seg:off or something.所有这一切都源于 x86-64 具有平坦的 memory model,而不是 seg:off 或其他东西。 And that function pointers have the same representation as data pointers.并且 function 指针与数据指针具有相同的表示。 On hypothetical machines (or C implementations) you might see something special for void* .在假设的机器(或 C 实现)上,您可能会看到一些特殊的void*

eg a machine that emulated CHAR_BIT=8 on top of word-addressable memory might have sizeof(char*) > sizeof(int*) , but void* would have to be wide enough to hold any possible pointer and might even have a different format than either.例如,在字可寻址 memory 之上模拟 CHAR_BIT=8 的机器可能具有sizeof(char*) > sizeof(int*) ,但void*必须足够宽以容纳任何可能的指针,甚至可能具有不同的格式比任何一个。 (Having a narrow char that you can't actually store in a thread-safe way (without a non-atomic RMW of the containing word) wouldn't be viable for C11.) (拥有一个实际上不能以线程安全方式存储的窄char (没有包含单词的非原子 RMW)对于 C11 是不可行的。)

Semi-related: Does C have an equivalent of std::less from C++?半相关: C 是否具有来自 C++ 的 std::less 等价物? talks about how C pointers might work in other hypothetical non-simple implementations.讨论 C 指针如何在其他假设的非简单实现中工作。 A seg:off pointer model wouldn't make void* different from int* though. seg:off 指针 model 不会使void*int*不同。

Adding to the answer above, memory has no type, whatsoever.除了上面的答案,memory 没有任何类型。 Any generally speaking, every pointer type is basically an unsigned long integer value, pointing to some address in the memory.任何一般来说,每个指针类型基本上都是一个无符号长 integer 值,指向 memory 中的某个地址。

Originally C language didn't have any void* , char* was the generic pointer type.最初 C 语言没有任何void*char*是通用指针类型。 And to quote from C: A Reference Manual :并引用C:参考手册

the problem with this use of char* is that the compiler cannot check that programmers always convert the pointer type properly这种使用char*的问题是编译器无法检查程序员是否总是正确地转换指针类型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM