【问题标题】:How are void pointers implemented?void 指针是如何实现的?
【发布时间】:2020-10-18 22:45:49
【问题描述】:

我想知道 void 指针是如何实现的。我试图用 x86-64 在 Godbolt 上找到它(你可以看到它here),但它没有透露任何东西。 void指针是如何实现的?

编辑: 这是我使用的代码:

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

我想在这里看到的只是x 的样子。我放 volatile 是为了让 gcc 不会把它当作死代码来消除。

【问题讨论】:

  • 我不确定您希望在那里看到什么。 y 位于 -12(%rsp),x 位于 -8(%rsp)。它将指向 y 的指针加载到 rax,将值 123 存储到 -12(%rsp),然后将 rax 存储到 -8(%rsp)。
  • 我建议在问题中包含您的实验代码,以及以这种方式设计该实验的某种原因。
  • @PeterCordes -- 我更新了我的问题。

标签: c pointers assembly x86-64 void-pointers


【解决方案1】:

一般来说,x86-64 处理器上的所有指针都是简单的 8 字节值,其中包含一些内存地址。只有编译器在乎他们指向什么。

【讨论】:

    【解决方案2】:

    在我看来,asm 清楚地表明void* 使用与其他指针相同的对象表示,例如int*,因此与void* 之间的转换是一个只保留编译器类型的空操作系统开心。

    asm 中的所有内容都只是字节,您可以根据需要对其进行整数运算。 指针只是可以取消引用的整数。 例如在 x86-64 asm 中,+1uintptr_t+1char* 没有什么不同,因为 C 将 sizeof(char) 定义为 1,并且 x86-64 是字节可寻址的,因此每个整数增量到指针是一个新字节。 (因此 x86-64 上的 C 实现使用 CHAR_BIT=8)。

    void* 只是一种可以保存任何指针值的类型,但这并不能让你用+1 或其他任何东西对其进行数学运算。 OTOH 在 C 中,您不需要强制转换以将其他指针类型分配给/从它。


    所有这些都来自具有平坦内存模型的 x86-64,而不是 seg:off 或其他东西。并且该函数指针具有与数据指针相同的表示。在假设的机器(或 C 实现)上,您可能会看到 void* 的特别之处。

    例如在字可寻址内存之上模拟 CHAR_BIT=8 的机器可能具有sizeof(char*) > sizeof(int*),但void* 必须足够宽以容纳任何可能的指针,甚至可能具有与两者不同的格式。 (有一个狭窄的char,你实际上不能以线程安全的方式存储(没有包含单词的非原子 RMW)对于 C11 是不可行的。)

    半相关:Does C have an equivalent of std::less from C++? 谈论 C 指针如何在其他假设的非简单实现中工作。不过,seg:off 指针模型不会使 void*int* 不同。

    【讨论】:

      【解决方案3】:

      除了上面的答案,内存没有任何类型。任何一般来说,每个指针类型基本上都是一个无符号长整数值,指向内存中的某个地址。

      原来C语言没有void*char*是通用指针类型。并引用C: A Reference Manual

      使用char* 的问题是编译器无法检查 程序员总是正确地转换指针类型

      【讨论】:

        猜你喜欢
        • 2016-09-13
        • 2014-05-30
        • 1970-01-01
        • 2013-08-20
        • 1970-01-01
        • 2016-09-07
        • 2013-12-18
        • 1970-01-01
        • 2021-09-02
        相关资源
        最近更新 更多