87

What would this statement yield?

void *p = malloc(sizeof(void));

Edit: An extension to the question.

If sizeof(void) yields 1 in GCC compiler, then 1 byte of memory is allocated and the pointer p points to that byte and would p++ be incremented to 0x2346? Suppose p was 0x2345. I am talking about p and not *p.

plasmacel
  • 8,183
  • 7
  • 53
  • 101
Lakshmi
  • 1,759
  • 4
  • 18
  • 23
  • 5
    FYI. This is non-standard C. In many compilers, this would be a compile-time error. – Johan Kotlinski Nov 03 '09 at 10:44
  • why do you need to know. Understanding this may help us answer the question. – Martin York Nov 03 '09 at 12:38
  • 4
    Commenting on your edit: yes, in GCC (only), incrementing a void pointer adds one to the value. If you value the portability of your code, do not abuse the liberty that GCC gives you. It is completely non-standard. And GCC admits as much with '-std=c99 -pedantic'. – Jonathan Leffler Nov 03 '09 at 15:45
  • 1
    Regular Void Proposal: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0146r1.html – alfC Oct 19 '19 at 21:28

10 Answers10

70

The type void has no size; that would be a compilation error. For the same reason you can't do something like:

void n;

EDIT. To my surprise, doing sizeof(void) actually does compile in GNU C:

$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc -w - && ./a.out 
1

However, in C++ it does not:

$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc++ -w - && ./a.out 
<stdin>: In function 'int main()':
<stdin>:1: error: invalid application of 'sizeof' to a void type
<stdin>:1: error: 'printf' was not declared in this scope
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
reko_t
  • 55,302
  • 10
  • 87
  • 77
  • 34
    But GCC has an option to treat 'sizeof(void) == sizeof(char)'...See -Wpointer-arith – Jonathan Leffler Nov 03 '09 at 09:37
  • 6
    @Jon this is for fools from the early 80's who were just starting to learn how to program. Standards were not widely decided upon. – unixman83 Jul 16 '11 at 14:56
  • 8
    `sizeof (void)` is a constraint violation. A conforming C compiler (which gcc is not by default) must at least warn about it, and may (and IMHO should) reject it. Reference: [N1570](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) 6.5.3.4p1 (`void` is an incomplete type). It's been this way since the 1989 standard, which introduced `void`. – Keith Thompson Feb 01 '15 at 03:06
  • 4
    @unixman83: That doesn't make sense. `void` didn't exist before it was introduced by the 1989 ANSI C standard, the same standard that made `sizeof (void)` a constraint violation. – Keith Thompson Feb 01 '15 at 03:06
  • 1
    Sizeof void is compiled because you need it to work with void* pointers. – kelin Oct 13 '15 at 16:27
  • 1
    Re: "you can't do something like `void n;`": FYI: however, you can do [`extern void n;`](https://stackoverflow.com/a/70949127/1778275). – pmor Sep 11 '22 at 20:13
46

If you are using GCC and you are not using compilation flags that remove compiler specific extensions, then sizeof(void) is 1. GCC has a nonstandard extension that does that.

In general, void is a incomplete type, and you cannot use sizeof for incomplete types.

hrnt
  • 9,882
  • 2
  • 31
  • 38
  • 2
    The option `-Wpointer-arith` is implied by `-pedantic`. I always used `-pedantic`. :) – Josh Lee Nov 03 '09 at 12:13
  • 1
    @jleedev Indeed, I also use -pedantic as much as I can. Unfortunately, though, some third party library headers make gcc -pedantic very sad :( – hrnt Nov 11 '09 at 15:33
  • 1
    +1 Really, why does GCC have thousands of useless extensions? –  Jan 25 '12 at 21:42
  • @user142019: because they are usefull ? And helps getting a consistent backend model through different programming languages and hardware architecture. – kriss Nov 26 '14 at 15:00
18

Although void may stand in place for a type, it cannot actually hold a value. Therefore, it has no size in memory. Getting the size of a void isn’t defined.

A void pointer is simply a language construct meaning a pointer to untyped memory.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 1
    so what ? Shouldn't any empty struct also consume no size in memory and that should be a problem. Well actually I wonder, if empty structs are truly using 0 bytes in C++ (as is true in C) looks like sizeof returns 1 for them. – kriss Mar 21 '13 at 09:22
  • 1
    @kriss I’m not sure what you’re saying but as you’ve noticed yourself, empty structs *do* occupy memory for reasons of object identity. – Konrad Rudolph Mar 21 '13 at 09:35
  • 1
    indeed, but it was not true in C and using memory for empty objects feels evil. – kriss Mar 21 '13 at 12:39
  • "Language construct" was the key to the question in my mind as to whether `void` can occupy memory. This question arises as a result of the interpretation of `void * p` based on C++ principles, which leads to the conclusion that `p` points to a memory location of type `void`, which is wrong! – Naghi Mar 07 '22 at 05:19
17

void has no size. In both C and C++, the expression sizeof (void) is invalid.

In C, quoting N1570 6.5.3.4 paragraph 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.

(N1570 is a draft of the 2011 ISO C standard.)

void is an incomplete type. This paragraph is a constraint, meaning that any conforming C compiler must diagnose any violation of it. (The diagnostic message may be a non-fatal warning.)

The C++ 11 standard has very similar wording. Both editions were published after this question was asked, but the rules go back to the 1989 ANSI C standard and the earliest C++ standards. In fact, the rule that void is an incomplete type to which sizeof may not be applied goes back exactly as far as the introduction of void into the language.

gcc has an extension that treats sizeof (void) as 1. gcc is not a conforming C compiler by default, so in its default mode it doesn't warn about sizeof (void). Extensions like this are permitted even for fully conforming C compilers, but the diagnostic is still required.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • I guess that they allowed `sizeof(void) == 1` for consistency with pointer arithmetic on `void` pointer, that is also a [gcc extension](https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-Arith). Citing from their documentation: `A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.`. But still diagnostic message should be present by default for C as Standard requires it. – Grzegorz Szpetkowski Feb 21 '15 at 11:51
  • 2
    @GrzegorzSzpetkowski: (Replying a couple of years later.) Yes, the standard requires a diagnostic, but gcc is not a conforming C compiler by default. Logically, the C standard imposes no requirements on implementations that do not claim to conform to it. gcc can be made to be (very nearly) conforming with the right command-line options, such as `-std=c11 -pedantic`. With such options, it does issue the required diagnostic. – Keith Thompson Sep 07 '17 at 23:59
12

Taking the size of void is a GCC extension.

pmg
  • 106,608
  • 13
  • 126
  • 198
6

sizeof() cannot be applied to incomplete types. And void is incomplete type that cannot be completed.

Aleksei Potov
  • 1,548
  • 11
  • 14
4

In C, sizeof(void) == 1 in GCC, but this appears to depend on your compiler.

In C++, I get:

In function 'int main()':
Line 2: error: invalid application of 'sizeof' to a void type
compilation terminated due to -Wfatal-errors.
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
0

To the 2nd part of the question: Note that sizeof(void *)!= sizeof(void). On a 32-bit arch, sizeof(void *) is 4 bytes, so p++, would be set accordingly.The amount by which a pointer is incremented is dependent on the data it is pointing to. So, it will be increased by 1 byte.

  • 1
    so p was pointing to 1 byte data since sizeof(void) gives 1 so p++ means p would be increment by 1 and not 4?? – Lakshmi Nov 03 '09 at 09:58
  • 1
    The amount by which a pointer is incremented is dependent on the data it is pointing to. So Yes. –  Nov 03 '09 at 10:32
  • p is of void* (void pointer) type, not void. So it would be incremented by the size of void* type (which is usually 4 in 32 bit systems). – Technowise Nov 03 '09 at 10:59
  • 4
    @Technowise: no. Any pointer of type `T*` is incremented by `sizeof(T)` (and *not* `sizeof(T*)`, which would almost always be the same, except *perhaps* for function pointers) when it is incremented. The exception is of course `void` (and again the exception is when having the GCC extensions enabled). – Konrad Rudolph Nov 03 '09 at 17:48
  • 1
    @Amit: How did you conclude that the size of the data a `void*` pointer points to is 1 byte? `sizeof (void)` is a constraint violation. (A gcc extension treats it as 1.) – Keith Thompson Feb 01 '15 at 03:09
-1

Most C++ compilers choosed to raise a compile error when trying to get sizeof(void).

When compiling C, gcc is not conforming and chose to define sizeof(void) as 1. It may look strange, but has a rationale. When you do pointer arithmetic adding or removing one unit means adding or removing the object pointed to size. Thus defining sizeof(void) as 1 helps defining void* as a pointer to byte (untyped memory address). Otherwise you would have surprising behaviors using pointer arithmetic like p+1 == p when p is void*. Such pointer arithmetic on void pointers is not allowed in c++ but works fine with when compiling C with gcc.

The standard recommended way would be to use char* for that kind of purpose (pointer to byte).

Another similar difference between C and C++ when using sizeof occurs when you defined an empty struct like:

struct Empty {
} empty;

Using gcc as my C compiler sizeof(empty) returns 0. Using g++ the same code will return 1.

I'm not sure what states both C and C++ standards on this point, but I believe defining the size of some empty structs/objects helps with reference management to avoid that two references to differing consecutive objects, the first one being empty, get the same address. If reference are implemented using hidden pointers as it is often done, ensuring different address will help comparing them.

But this is merely avoiding a surprising behavior (corner case comparison of references) by introduction another one (empty objects, even PODs consume at least 1 byte memory).

kriss
  • 23,497
  • 17
  • 97
  • 116
  • 7
    “C chose instead to define sizeof(void) as 1.” – No, that’s wrong. `sizeof(void)` is not defined in C, same as in C++. GCC simply is not conforming in this point, and pointer arithmetic on `void` pointers is simply not defined either – `void* p; p++;` is invalid. Even GCC will give you a warning when compiling with the `-pedantic` flag. And you are also wrong about the default behaviour of GCC for C++: by default *this is treated as an error*. – Konrad Rudolph Mar 21 '13 at 09:37
  • @Konrad: yes, I'm quite sure it was not true with older version of gcc, but up to date ones do as you say. – kriss Mar 21 '13 at 12:40
  • At least in C, an empty `struct` definition is a syntax error; gcc's support is an extension. They may be valid in C++; I'm not sure. – Keith Thompson Feb 01 '15 at 03:20
-1

while sizeof(void) perhaps makes no sense in itself, it is important when you're doing any pointer math.

eg.

 void *p;
 while(...)
      p++;

If sizeof(void) is considered 1 then this will work. If sizeof(void) is considered 0 then you hit an infinite loop.

user906752
  • 15
  • 1
  • 4
    The example code snippet is illegal in C and C++. Some compilers allow it anyway. – James Sep 13 '13 at 17:05
  • 1
    No, it's not important at all (though the authors of gcc apparently thought it was). If you want to do pointer arithmetic on byte pointers, use `unsigned char*`. – Keith Thompson Feb 01 '15 at 03:07
  • @KeithThompson - even `char` is not guaranteed to be 1 byte. I have worked on a system that set it to 32 bits. – ash Oct 23 '19 at 23:45
  • @ash: Yes, `char` is guaranteed to be 1 byte. If you've worked on a system with 32-bit `char`, then a byte on that system is 32 bits (`CHAR_BIT == 32`). That's how the C standard defines "byte". C standard, 6.5.3.4 paragraphs 2 and 4: "The **`sizeof`** operator yields the size (in bytes) of its operand. [...] When **`sizeof`** is applied to an operand that has type **`char`**, **`unsigned char`**, or **`signed char`**, (or a qualified version thereof) the result is 1." – Keith Thompson Oct 24 '19 at 00:02
  • When did C standard 6.5.3.4 come out? I worked on this system back in the mid 90's. – ash Oct 29 '19 at 18:57
  • @ash Just saw your comment (if you had used the "@" syntax I would have been notified). I was referring to section 6.5.3.4 of the C standard. It's section 6.3.3.4 of the 1990 ISO C standard, the one that was current in the mid 1990s. – Keith Thompson Sep 20 '20 at 20:55
  • @KeithThompson makes sense. It's important to know which standards are in-play. – ash Sep 21 '20 at 22:32