1

Since a C pointer returns a "void*", and in addition to its own address it might refers somehow to the memory size reserved by malloc(size), i ask myself if declaration of "void*" is actually something completely unrelated to the type "void" used to execute procedures and if "void*" is actually a kind of type that self contain informations like the allocated memory block size, with an "internal" structure similar to the one showed below.

//An imaginary internal implementation of "type" void* used to create pointers

struct void*
{
    char[4] address; //for 32bit systems;
    int size; //memory block size;
};

void* ptr=malloc(10); //create a pointer called ptr of 10 bytes
Paolo
  • 173
  • 2
  • 9
  • A `void*` is a pointer, like any other pointer. Thus it behaves like other pointers, not like `void`. One thing to note is that you can't do pointer arithmetic on it because that depends on the size of what it's pointing to, and you can't do that with `void`. – Blaze Mar 19 '19 at 08:02
  • *"and in addition to its own address must refers somehow to the memory size reserved by malloc(size)"* - That's quite an extrapolation you make – StoryTeller - Unslander Monica Mar 19 '19 at 08:03
  • 3
    I removed the C++ tag, since if your code is `void* ptr=malloc(10)` - it can only be C, that implicit conversion to `void*` does not exist in C++. – StoryTeller - Unslander Monica Mar 19 '19 at 08:05
  • @StoryTeller; You wrecked my answer (which isn't one of my best anyway) ;- although you make a good point. – Bathsheba Mar 19 '19 at 08:06
  • 1
    @Bathsheba - That second paragraph didn't do your answer any favors anyway :P – StoryTeller - Unslander Monica Mar 19 '19 at 08:06
  • @StoryTeller: Ouch. I needed a boost today too. – Bathsheba Mar 19 '19 at 08:06
  • @Blaze: Pointer Arithmetic is exactly the reason why i begin to think about the internal implementation of void* type and so what is the difference between void and void* beside the semantics that is clear. – Paolo Mar 19 '19 at 08:07
  • @StoryTeller: I know but actually its the only imaginary construction of a pointer in the system memory. Since i have no idea how is a pointer implemented in memory, i guessed it is a kind of struct. I am very happy to discover how is pointer actually implemented in system memory. – Paolo Mar 19 '19 at 08:10
  • 1
    @Paolo: Restricting my comment to Intel chips, they don't have pointers. Just registers. – Bathsheba Mar 19 '19 at 08:11
  • 2
    It doesn't matter how a pointer is implemented. `malloc` doesn't have to rely on `void*` storing the size of the object. That's what I meant by you extrapolating here. Yes, the size must be known, but it's quite a leap to assume the pointer itself must hold it somehow. – StoryTeller - Unslander Monica Mar 19 '19 at 08:11
  • The key is to separate the keyword `void` (used to indicate that a function takes no parameters or provides no return) and the pointer `void*` which is just a pointer than can represent any type but cannot be deferenced without having been cast to an appropriate type first.. – David C. Rankin Mar 19 '19 at 08:22
  • @Paolo: Somewhat related: https://stackoverflow.com/questions/52195836/can-i-use-pointer-arithmetic-on-pointers-to-void-pointers/52196548#52196548 – P.W Mar 19 '19 at 08:24

4 Answers4

5

The use of the keyword void may indeed have a different semantic depending on the context:

  • It can mean nothing such as in void myfunction(...) { ... } or in int my_other_function(void) {...}
  • It can mean anything such as in void *p = ...;

In C a void pointer is a pointer that can point to anything. In C++ as well, but the usage should be avoided as much as possible and std::any should be preferred.

Important remark about your imaginary implementation: a void pointer does not istself know anything about the size of the object it points to.

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • `std::any` in C ain't gonna end well. Also you might want to mention the use of `void` as the single parameter in a function prototype, e.g. `int foo(void)`. – Bathsheba Mar 19 '19 at 08:09
  • @Bathsheba indeed ! `f(void)` is another example for *nothing*. – Christophe Mar 19 '19 at 08:13
  • I leave the `std::any`is there only because when I answered, the question was still labeled C/C++ – Christophe Mar 19 '19 at 08:15
  • Unless you're a Time Lord, @StoryTeller 's edit was made 4 minutes before this answer went up. Just sayin' – Bathsheba Mar 19 '19 at 08:15
  • "Important remark about your imaginary implementation: a void pointer does not itself know anything about the size of the object it points to." Great :):). – Paolo Mar 19 '19 at 08:18
  • @Bathsheba when I read the question and started typing the answer, believe me or not, the label was there, and I did not get a refresh until I posted it. That’s not time lord logic but simple transactional consistency ;-) – Christophe Mar 19 '19 at 08:44
  • @Paolo I cannot see if your comment is genuine or ironic. I made this remark because OP provided a piece of code where he imagined an implementation of a void pointer using an address *and* a size, which might suggest a misconception. – Christophe Mar 19 '19 at 08:51
  • @Christophe Was genuine, in fact is a relief that a void pointer is just a pointer and nothing else. Though, this let me a little lost in understanding who "holds" the size of the memory block in order to be able to make pointer arithmetics (i hope to not make anybody disgusted with this sentence).Annti Haapala below gave some good hints about the type void and in fact maybe my question is wrongly posed since does not exist a void* type but does exist a pointer to a type "void" that is said to be an "an empty set of values" and that "it is an incomplete object type that cannot be completed". – Paolo Mar 19 '19 at 09:01
  • @Paolo But why do you think you need to know "size of the memory block" to do pointer arithmetic on a pointer to that block? – HolyBlackCat Mar 19 '19 at 09:06
  • @HolyBlackCat suppose i define (in visual c++) "int *ptr =(int*)malloc(10)" so to create a pointer named ptr that refers to its address and 10bytes forward. If i executes ptr++, the program will point 4 bytes forward (still in the reserved memory of 10bytes). Since ptr it's just a pointer (4byte in 32bit sys), I don't understand if the information how to increment itself, and how big is the memory reserved, are data stored in the program/data memory or if they are information used by the compiler and later lost. I don't wish to claim any true, it's just that i don't get the "mechanics". – Paolo Mar 19 '19 at 09:28
  • 2
    @Paolo *"information how to increment"* Information on how to increment a pointer is determined at compilation time, not runtime (it affects generated code; otherwise it's not necessary to store it anywhere at runtime); it's determined from the pointer *type*. I.e. `int *ptr` is always incremented in 4-byte steps (if `sizeof(int) == 4`), no matter what you assign to it. And `void *ptr` can't be incremented at all, again no matter what you assign to it. – HolyBlackCat Mar 19 '19 at 10:23
  • 2
    *"and how big is the memory reserved"* This information might be useful only for `free`; if `free` needs it, then it's probably stored near the `malloc`ed block. It's an implementation detail of `malloc`/`free` that you shouldn't worry about. – HolyBlackCat Mar 19 '19 at 10:24
  • @HolyBlackCat Thank you for these brilliant explanations about void pointer arithmetics and the clean delineation with the malloc/free. – Christophe Mar 19 '19 at 10:28
  • @HolyBlackCat & Everybody: Thanks for such interesting morning discussion! :) – Paolo Mar 19 '19 at 10:57
  • @Paolo Thanks for your interesting question that raised all these constructive exchanges – Christophe Mar 19 '19 at 11:03
2

void has more than one use; that's all. void and void* are very different beasts. Note that void* is not a keyword, but void is.

Don't think of a void* as being your structure. It's merely a pointer that's been converted from another type by a cast. malloc returns a void* that's convertible to another pointer type by a mechanism that somewhat paradoxically makes it impossible to write malloc in portable C.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • "malloc returns a void* that's convertible to another pointer type". So actually what is void* in sytem memory? is struct, a class (i doubt since we speak in C), some stuff that is never exposed to the language...i have no idea how a pointer is actually implemented since beside its address, also keep the memory size information... – Paolo Mar 19 '19 at 08:13
  • 2
    @Paolo: `void*` is merely a pointer without type information. – Bathsheba Mar 19 '19 at 08:14
  • 1
    @Paolo The content of a pointer variable is only an address, no extra information about the size of a memory block. It's up to the memory manager to keep track of allocated blocks but this is not stored in the pointer variable. – Gerhardh Mar 19 '19 at 09:39
1

No, they're not completely unrelated. void is a type that (C11 6.2.5p19)

comprises an empty set of values; it is an incomplete object type that cannot be completed.

And void * is a pointer type that points to an object of the said type.

Any object pointer type can be converted to another object pointer type with an explicit cast, given that the pointer is suitably aligned; the only conversion between pointer types that can happen without a cast in C are conversions to void * and back again; hence the void * status as the generic pointer type.

The void type in itself can be used for other tasks - for example an expression can be cast to void to signal that the value is being deliberately ignored, or used as the return value type to signal that the function does not return a value. The only semantic overload is the use of void in a prototype: int func(void) to signal that the function does not take any arguments.

  • Very interesting explanation. So in general a Type is meant to be a "set of values" stored somewhere in memory that selfdescribe itself? What do you mean for "given that the pointer is suitably aligned"? According to your explanation, the title of my post should be changed in order to clarify that void* is not a type...but i don't know how to edit the question in order to give means to all the answers and comments actually provided. – Paolo Mar 19 '19 at 08:48
  • @Paolo no, a type means a set of possible values of which an object of the given type can hold *one* at any given instance. – Antti Haapala -- Слава Україні Mar 19 '19 at 08:51
1

void* ptr=malloc(10); creates 10 bytes of raw, uninitialised data on the heap. That data does not at this point have a type.

It does not "create a pointer called ptr of 10 bytes". The variable ptr is of sizeof(void*) bytes and allocated as "automatic storage" (likely on the stack), regardless of where you let it point.

See A program uses different regions of memory for static objects, automatic objects, and dynamically allocated objects for an explanation of where different variables are likely allocated on mainstream computers.

Lundin
  • 195,001
  • 40
  • 254
  • 396