【问题标题】:What data type does memory see when I use void?当我使用 void 时,内存会看到什么数据类型?
【发布时间】:2009-05-05 20:20:27
【问题描述】:

当我创建一个 int 类型的方法时,编译器会在内存中保留 X 个位数。那么如何看到一个 void 类型呢? void 类型占用多少位/字节?

【问题讨论】:

  • 你说的是函数的返回值吗?
  • 没有其他人阅读这个问题吗?他说'int类型的方法'我认为他的意思是'返回int的方法'。他没有问空指针占用了多少空间。请澄清。

标签: c# c++


【解决方案1】:

void 类型不占用任何位。您不能声明 void 类型的变量。这个:

void a;

导致编译错误。
void 只是一个占位符,表示“无”一个返回 void 的函数不返回任何内容,一个以 void 作为参数的函数不接受任何参数。

但是,您可以声明 void* 类型的变量:

void* a;

这只是声明了一个可以指向任何东西的指针。与任何指针一样,它采用指针类型的大小,即 sizeof(void*) 在 32 位系统中通常等于 4。

【讨论】:

  • 我认为他说的不是变量,而是函数签名。
【解决方案2】:

我认为您对编译器如何存储返回值的假设可能过于笼统。返回值的情况取决于语言、类型和硬件。

可能有一个“返回寄存器”可以保存返回值,因此不会占用内存。 “返回寄存器”也可以根据返回的类型指向内存中分配的一些内容。

我不明白为什么返回 void 的函数会为返回值分配内存。

【讨论】:

    【解决方案3】:

    在 x86 架构上(使用 gcc 3.4.6),int 函数的返回值存储在 eax 寄存器中。浮点数通过 XMM 寄存器或在 ST0 中返回。 [编辑:感谢巴斯蒂安伦纳德!]

    Void 函数根本不将任何东西放入 eax 并返回。

    #include <stdio.h>
    
    int f1(void)
    {
        printf("f1\n");
        return 9.0f;
    }
    void f2(void)
    {
        printf("f2\n");
    }
    
    double f3(void)
    {
        return 10.0;
    }
    
    int main(void)
    {
        int x = f1();
        f2();
        double y = f3();
        return 0;
    }
    

    使用 gcc -S 构建到:

    main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $24, %esp
        andl    $-16, %esp
        movl    $0, %eax
        addl    $15, %eax
        addl    $15, %eax
        shrl    $4, %eax
        sall    $4, %eax
        subl    %eax, %esp
        call    f1
        movl    %eax, -4(%ebp)
        call    f2
        call    f3
        fstpl   -16(%ebp)
        movl    $0, %eax
        leave
        ret
        .size   main, .-main
        .section        .note.GNU-stack,"",@progbits
        .ident  "GCC: (GNU) 3.4.6"
    

    定义了 f2:

    f2:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        subl    $12, %esp
        pushl   $.LC1
        call    printf
        addl    $16, %esp
        leave
        ret
        .size   f2, .-f2
    

    和 f1 定义:

    f1:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        subl    $12, %esp
        pushl   $.LC0
        call    printf
        addl    $16, %esp
        movl    $9, %eax
        leave
        ret
    

    如果其他人从不同版本的 gcc 中获得不同的代码,那么看到 XD 会很有趣(也许在其他情况下 int 函数会返回堆栈...)

    我想在所有实现中,一个 void 函数只是什么都不返回。它要么单独留下返回寄存器和/或不将任何内容放入(或放入)堆栈中。

    【讨论】:

    • 在linux上的x86和x86_64平台上,int函数永远不会使用栈返回。如果您想查看堆栈上的返回值,请尝试在 x86 上返回 long long,或者在任何平台上返回大型结构(或类)。
    • @ParoXoN:float 和 double 在 ST0 或 XMM 寄存器中返回(在您的代码中,f3 的返回值是使用 FSTP 检索的,它“弹出”ST0)。
    【解决方案4】:

    如果函数返回void,调用者不期望任何返回值并且不需要分配任何东西。 void 不是要返回的真实类型,它更多的是向编译器表明该函数不返回任何内容。

    在 PC 上,函数通过将它们放在特定寄存器 (eax) 中返回简单的值,例如 int;编译器只需生成适当的代码来检索此值。 (如果函数返回void,那么编译器就不会生成这种代码。)
    在其他架构上,调用者可能会隐式传递一个指向 int 的参数,其中将放置返回值。

    C 和 C++ 标准没有规定这种低级的东西。它可能由另一个标准指定,也可能只是一个约定。

    对于C#,我想答案在于如何在CIL 中获得返回值。

    【讨论】:

      【解决方案5】:

      在 C 或 C++ 中本身没有 void 类型(我对 C# 一无所知)。 void * 是一个无类型指针。

      这可能会有所帮助:http://c-faq.com/ansi/voidparith.html

      【讨论】:

      • 我认为他说的不是变量,而是函数签名。
      • malloc 返回一个 void * ... 这是一个通用指针,指向通过调用分配的内存区域。在 C 中,从 void * 到其他类型的指针的转换是自动的。返回的指针指向的内存大小是作为 malloc 的参数指定的大小。仍然没有 void 数据类型。在参数列表中使用,它指定函数不接受任何参数。
      【解决方案6】:

      它只是一个未定义的指针类型,所以它的大小是你创建它的系统上任何其他指针的大小。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-16
        • 2019-07-10
        • 2017-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多