A generic vector only works with pointers? Why?

Asked

Viewed 134 times

1

Hello,

I know it works:

typedef struct stack TStack;
struct stack
{
    int size;
    int top;
    void **S; // <------ vai apontar para um vetor de ponteiros 
              // tipo void*, que pode ser de qualquer tipo
};

But why can’t I:

typedef struct stack TStack;
struct stack
{
    int top;
    void S[10]; // <----- de modo que S guarde qualquer coisa
};

That is, for me to make a generic stack TAD, for example, the only way to do it is by using void*? There is no way to just declare that the vector is generic?

Just like we do with int vet[5];? If not, for what reason?

  • 1

    Just to leave a slightly loose remark, void **S is not a vector.

  • @Isac, yes, void **S is not a vector, it is a p-to-p pointer (pointer to pointer). In this case above I did not show, but I used a malloc to allocate a pointer vector of the type void*, and S points to this vector.

1 answer

2


Types void and void*

void and void* They’re actually very different types.

The void means "nothingness", therefore does not occupy any space in the computer memory. Therefore it is used as return value of functions that do not need to return anything.

The void* is a pointer for something undetermined. When you’re going to use it for something, you’ll need a cast for the real type. The size of the void* is the size of a normal pointer (or the largest pointer possible, in the case of architectures where there are pointers of different sizes). void* takes space in memory, void does not.

Why doesn’t a void vector make sense

A vector/array in C is a sequence of bytes representing several objects of the same type one after the other. So, if void occupies 0 bytes, void vet[5] occupies 0 bytes and void s[10] occupies 0 bytes as well (but see: https://stackoverflow.com/questions/1666224/what-is-the-size-of-void).

But it does make sense to have a pointer to any memory area that will be reinterpreted later, so void* is valid.

Note: although C makes vectors and pointers get confused in various situations, they remain different types and from time to time we come across these cases.

A construction that is valid and may be what you need is to make a void* pointer array. In this case the syntax is:

void *s[10]; // Leia como: vetor de 10 ponteiros void*

How to get any memory block

Unlike void, which has size 0, char has size 1, so if you need a type "memory string without caring about type", use char[] (or unsigned char[]). Although in this case another solution is to call malloc() to dynamically allocate memory.

However, swapping void[] for char[] (or malloc) is not exactly a complete solution to your problem as it will require several code adaptations. For example, in the same block of 8 bytes fit two floats or only one double and you would have to take this into account (use sizeof). If you call malloc(), you will need to remember free().

Support for generic C types

Support for generic C types is not very complete, you need to build your own conventions and abstractions when creating a library. You can use pointers to abstract the fact that different types have different sizes or you can try to put everything into a memory block and make sure it fits everything you want. Anyway the solution does not come ready, as in C++.

  • 1

    Ever tried to make sizeof(void)? You will see that it occupies 1 byte. So much so that void* accepts pointer arithmetic with elements 1 byte in size.

  • @There would not be a similar form using size_t ?

  • @Jeffersonquesado Is that right? I remembered that there were some "pranks" as to the size of the void (which I ignored so as not to complicate the answer too much), but I didn’t think it was anything as absurd as that, hahaha. Maybe the question code should be valid then, huh? I also thought it might be one of those small differences between C and C++, a complicated area. If you have an idea to improve the answer without changing the essence, you can propose an edition. I am now out of time to reformulate.

  • @Fourzerofive size_t is nothing but a number (an unsigned number). I don’t see what it would help.

  • 1

    @Very interesting, your answer. So void* represents a pointer that can point to anything, and void represents an empty guy. It’s two different things. Now it’s clearer to me. Thank you!

  • 1

    @Jeffersonquesado put a link to the S.O. in English about sizeof(void), for those who want more information about the details. Everything indicates that it is a GCC extension. It is clearer with the link, right?

  • @Funny that in all the corners I tested, sizeof(void) I always returned 1 (apparently they should all be based on GCC). I had this for granted of the language. I learned something new today thanks to your link.

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.