2

Having this simple code:

#include <stdio.h>

typedef struct
{
    int a;
    char c;
} foo;

void func(void *arg)
{
    printf("sizeof arg: %ld\n", sizeof(*arg));
}

int main()
{
    foo f = {6, 'c'};
    func(&f);

    printf("the real sizeof struct foo: %ld\n", sizeof(f));
}

output:

sizeof arg: 1
the real sizeof struct foo: 8

As you can see the function shows wrong result. If the reason is invalid application of ‘sizeof’ to incomplete type, then why does it shows sizeof arg: 1? void is not 1 bytes long, but incomplete type, so why is this result?

milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • 1
    https://stackoverflow.com/questions/1666224/what-is-the-size-of-void – Clifford Feb 01 '21 at 22:16
  • 1
    You are getting confused by a poorly thought out language extension that some practical joker with a wicked sense of humour decided to enable in GCC by default. My recommendation is to disable all language extensions. `-std=c11 -Wall -Werror -pedantic` is one way to do so. – n. m. could be an AI Feb 01 '21 at 22:18
  • Given `void *arg`, `sizeof( *arg )` is invalid code. You can't dereference a `void *` pointer. – Andrew Henle Feb 01 '21 at 23:57

3 Answers3

7

You're attempting to get the size of void which the C standard doesn't allow. However, some implementations define sizeof(void) to be 1 which is what you're seeing here.

The function has no way of knowing that the void * you passed it is actually a foo *. You would need some other way of conveying that information.

dbush
  • 205,898
  • 23
  • 218
  • 273
2

This statement

printf("sizeof arg: %ld\n", sizeof(*arg));

is incorrect. The expression *arg has the incomplete type void. You need to write

printf("sizeof arg: %ld\n", sizeof(* ( foo * )arg));

Early versions of C do not have the type void. Instead the type char was used as the type void. As the sizeof( char ) is always equal to 1 then some compilers for backward compatibility with the old specifications of C set sizeof( void ) to 1 though it is not correct from the C Standard's point of view.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

The result should be a diagnostic, as sizeof (void) (which sizeof (*arg) resolves to) is a constraint violation:

6.5.3.4 The sizeof and _Alignof operators

Constraints

1    The sizeof operator shall not be applied to an expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an expression that designates a bit-field member. The _Alignof operator shall not be applied to a function type or an incomplete type.
C 2011 Online Draft

void is an incomplete type that cannot be completed - you cannot create an object that type, so using sizeof on it is a coding error, full stop.

However, for some reason, certain implementations decided to have sizeof (void) evaluate to 1 unless you're in "pedantic" mode. Obviously someone thought it was useful in some circumstances, but I wouldn't recommend its use.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • 1
    For some strange reason, I can't quite connect "break the language (literally!) in a way that confuses new programmers" with "useful". – Andrew Henle Feb 02 '21 at 00:00
  • @AndrewHenle — take up the discussion with the GCC team (and, AFAIK, `clang` implements `sizeof(void) == 1` for compatibility with GCC). OTOH, it is probably 20 years too late to affect the GCC decision; backwards compatibility means it is here in perpetuity. See [Arithmetic on void and function pointers](https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gcc/Pointer-Arith.html#Pointer-Arith). – Jonathan Leffler Feb 02 '21 at 02:00