Thursday, May 5, 2011

What data type does memory see when I use void?

When I create a method of type int the compiler reserves X number of bits in memory. So how does the see a void type? How many bits/bytes does a void type take up?

From stackoverflow
  • I think the assumption you made about how a compiler stores return values might be too generic. What happens with return values is determined by the language, the type, and the hardware.

    There might be a 'return register' that could hold the value of the return, so no memory would be taken up. The 'return register' could also just point to some allocated in memory based on the type being returned.

    I don't see why a function returning void would ever have allocated memory for the return value.

  • There is no void type per se in C or C++ (I don't know anything about C#). void * is a typeless pointer.

    This might be of some help: http://c-faq.com/ansi/voidparith.html

    MStodd : I don't think he's talking about variables, but function signatures.
    Sinan Ünür : malloc returns a void * ... That is a generic pointer to the area of memory allocated with the call. In C, conversion from void * to other types of pointer is automatic. The size of the memory pointed to by the returned pointer is the size which was specified as the argument to malloc. There is still no void data type. Used in the argument list, it specifies that the function takes no arguments.
  • It's just an undefined pointer type, so the size is the size of any other pointer on the system you're creating it on.

  • the void type does not take any bits. you cannot declare a variable of type void. this:

    void a;
    

    causes a compilation error.
    void is just a place holder that means "nothing" a function that returns void returns nothing and a function that takes void as an argument, takes no arguments.

    You can however declare a variable of type void*:

    void* a;
    

    This simply declares a pointer that can point to anything what so ever. as any pointer, it takes the size of a pointer type, i.e. sizeof(void*) which typically equals 4 in 32 bit systems.

    MStodd : I don't think he's talking about variables, but function signatures.
  • On an x86 architecture (using gcc 3.4.6,) the return value of int functions is stored in the eax register. Floating-point numbers are returned via an XMM register or in ST0. [Edit: Thanks Bastien Leonard!]

    Void functions simply don't put anything into eax and return.

    #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;
    }
    

    builds with gcc -S to:

    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"
    

    with f2 defined:

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

    and f1 defined:

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

    If other people get different code from different versions of gcc, that would be interesting to see XD (Maybe in other situations int functions return on the stack...)

    I would imagine that in all implementations, though, a void function simply returns nothing. It either leaves the return registers alone and/or drops nothing on (or into) the stack.

    bdonlan : On x86 and x86_64 platforms on linux, int functions will never use the stack to return. Try returning a long long on x86, or a large struct (or class) on any platform if you want to see returns on the stack.
    Bastien Léonard : @ParoXoN: float and double are returned in ST0 or an XMM register (in your code f3's returned value is retrieved with FSTP, which "pops" ST0).
    ParoXoN : Ah that makes sense, thanks :) My mistake!
  • It the function returns void, the caller doesn't expect any return value and nothing needs to be allocated. void isn't a real type to be returned, it's more an indication to the compiler that the function returns nothing.

    On PC, functions return simple values like int by placing them in a particular register (eax); the compiler simply generates the appropriate code to retrieve this value. (And if the function returns void, then the compiler doesn't generates this kind of code.)
    On other architectures, the caller might implicitly pass a parameter pointing to an int where the return value will be placed.

    This kind of low-level stuff isn't specified by the C and C++ standards. It may be specified by another standard, or it may be just a convention.

    For C#, I guess that the answer lies in how you get a return value in CIL.

0 comments:

Post a Comment