Dynamic allocation in C-unknowingly allocating the total amount of elements

I am having a doubt regarding dynamic allocation in c, as to the use of function malloc().

If we take, for example, a case of registration of a full name, as we have no way to know the amount of characters, we create the malloc(), in this way, the field will fit the exact size typed by the user, correct?

But in every example I see, there is the insertion of the amount of bytes that will be allocated, example:

char *c = malloc(sizeof(char) * quantidade_de_elementos_que_vou_ter_no_meu_vetor;

That is, in that in case I'm allocating quantidade_de_elementos_que_vou_ter_no_meu_vetor times the size of a char. However, the object to use malloc(), wouldn't it be because I don't know the total amount of elements?

That is, I do not need to kick a static size, delimiting the maximum amount of elements. Using this variable quantidade_de_elementos_que_vou_ter_no_meu_vetor doesn't take away that purpose?

If I know the total amount of elements, what's the difference then from already defining a static size? Example:

char c[20]; 

What I know is that if I make a dynamic allocation, the allocation of memory will be done in the execution of the program, and not in its compilation, as occurs when there is the definition of a static vector.

The reason for having to use an allocation of type:

char *c = malloc(sizeof(char) * quantidade_de_elementos_que_vou_ter_no_meu_vetor;

Would it be because in C language, I need to know the size of my vector to get traverses the same?

Still using this line of code above as an example, if I say that:

quantidade_de_elementos_que_vou_ter_no_meu_vetor = 20;

Means I will be allocating 20 bytes (sizeof (char) * 20, considering that size of a char is equal to 1), right? What if in this case, I entered a word that had only 10 characters? Would I occupy only the first 10 spaces and the other 10? Would there be a waste in that case then?

Author: Maniero, 2018-11-21

3 answers

If we take, for example, a case of registration of a full name, as we have no way to know the amount of characters, we create the malloc(), in this way, the field will fit the exact size typed by the user, correct?

Generally not, it is common for you to set a maximum size that the name will have and allocate that amount. Eventually further optimizations can be made if necessary. Almost always you choose if you want to have the best memory consumption or as little processing as possible.

Is it possible to use a realloc(), but in most cases it does not compensate for the effort. It will increase the allocation as needed, but it is almost always a worse solution. example .

But in every example I see there is the insertion of the amount of bytes that will be allocated, example:

char *c = malloc(sizeof(char) * quantidade_de_elementos_que_vou_ter_no_meu_vetor;

That is, in this case I will be allocating quantidade_de_elementos_que_vou_ter_no_meu_vetor times the size of a char. However, the object to use malloc(), wouldn't it be because I don't know the total amount of elements?

No, the purpose of its use is to allocate in dynamic memory, usually the heap (at least it is so in all "serious" implementations of Standard C. That alone, you have to know the amount of bytes to be allocated.

That is, I do not need to kick a static size, delimiting the maximum amount of elements. Using this variable quantidade_de_elementos_que_vou_ter_no_meu_vetor doesn't it take away that purpose?

Your concept of "static size" and every use of the term static out there is incorrect, static is something else, it is something that is immutable since Application startup and defined during compilation, so they cannot receive values at runtime.

See What prevents an array from being initialized with a variable size in C?. Or still How to store any string in C?.

And what is the char size? is always 1 , so I feel like crying when they use sizeof(char).

If I know the total amount of elements, what is the difference then from already defining a static size? Example:

char c[20]; 

This syntax determines that it is allocated in automatic memory (which is not static), i.e. the stack (so it will only exist in the scope where it was created). It is the only important difference for the malloc(), even because the malloc() it also requires a known size. There is no magic, there is no elasticity. See What is the difference between pointer to vector and pointer to variable?.

What I know is that if I do a dynamic allocation, the memory allocation will be done at the execution of the program, and not at its compilation, as occurs when there is the definition of a static vector.

In practice all allocation is made in execution. There is no such thing as allocation in the build. Exist allocation defined during compilation that occurs in the static area. Even in the automatic area the size can be set at the time of need, and of course, it will be done only in execution. Something like this is allowed:

char c[x]; //x é lido pelo teclado antes desta linha

The reason for having to use an allocation of Type:

char *c = malloc(sizeof(char) * quantidade_de_elementos_que_vou_ter_no_meu_vetor;

Would it be because in C language, I need to know the size of my vector to get traverses the same?

No, that's incorrect. Use like this because you want that the life time of the object is disassociated from the life time of the function (such as the automatic area) that created it, or else you want to ensure that the size of the object does not create complicators for the stack that has a limited size, in this case you are making sure because you know that stack Overflow.

Still using this line of code above as an example, if I say that:

quantidade_de_elementos_que_vou_ter_no_meu_vetor = 20;

This is just assigning the value 20 to a variable with a very long name that must already be previously declared. The rest is speculation.

Means I'll be allocating 20 bytes(sizeof (char) * 20, considering that a char's size is equal to 1), right?

Yes.

What if in that case, I entered a word that had only 10 characters? I would occupy only the first 10 spaces and the another 10? Would there be a waste in that case then?

In a way, yes. I do not know if you can call it waste, but in fact it is unused. It's normal. There are so many other" waste " that most programmers never realize. There are cases that the "waste" (overhead) of a vector in the stack is smaller, or at least not much larger than that of using the malloc(). Almost all implementations of malloc() "waste" space (those that do not have other problems worse, so they are not even used in fact). Not to mention that it is much more complicated to manage it. And E has a worse performance in almost all cases . It should always be the last option in most scenarios.

May be useful:

 6
Author: Maniero, 2020-08-17 19:11:52

Since we have no way to know the amount of characters, we created the malloc, in this way, the field will fit the exact size typed by the user, correct?

Incorrect, both in static and dynamic allocation the size has to be set and there is no automatic adjustment. If you have reserved space for 20 characters then you can only keep 20 careteres.

But in every example I see, there is the insertion of the amount of bytes that will be allocated

Is precisely how the function works. If you look at the documentation you see that only one parameter is received, the amount of bytes to allocate. This means that malloc(34) indicates that you want to request an area of in memory that is 34 bytes in size. It is then up to you to say the correct amount of bytes for what you intend to save.

However, the object of using malloc, would not be because I do not know the total amount of elements?

Not really. The biggest motivation for using dynamic allocation would be to make the memory space hold until it is done free. In contrast, in the static allocation you exemplified with char c[20]; at the end of the function this array of chars is released and can no longer access it.

What if in that case, I entered a word that had only 10 characters? Would I occupy only the first 10 spaces and the other 10? There would be a waste in this case so?

Uses the first 10 and has yet to use one more for the Terminator, otherwise it does not have a properly terminated string. The rest remain unused and have the value that was already in the memory, which in our eyes end up being random.

 4
Author: Isac, 2018-11-21 22:37:27

You're right, but you're not right ;)

When you allocate memory you have to know how much you will allocate, is the parameter for malloc(): the number of bytes.

But you're perhaps oversimplifying the problem: following with Your Name example, let's focus on city names and consider 4, with the number of letters in parentheses. included a space for the final zero:

Santos (7) 
Brasília (9)
Itú (4)
itapecirica da Serra (21)

When you create a city register using a fixed size for each city will allocate memory for these names using what size? The size of the "biggest" city, right?

char cidades[4][21];

For these 4 will be 84 bytes. However they only have 41 in total. With these 4 cities are already gone 43 bytes in waste.

This is why one uses a static area, large enough to contain the longest city name, such as

char uma_cidade[512];

And from this area one creates a structure like

char** cidades;
int    nCidades;

To save all cities and the number of cities, using dynamic allocation and allocating only the space needed for the city name and a 0 at the end to end the string.

Any resemblance to what the system does with every C program is because it is the same thing: the prototype of main() is

int main(int argc, char** argv)

And the system mounts the list with the arguments, each a string, terminated by zero, and says in argc how many are. What if you call your program x like this:

x azul 32 verde

Your program receives

argc = 4;
argv[0] = "C:\x.exe"
argv[1] = "azul"
argv[2] = "32"
argv[3] = "verde"

All strings with the minimum size and finished by zero.

I posted an example that does this for int**

Would be because in C language, I need to know the size of my vector to getting runs the same?

In the case of a vector of char, such a string, in C they are terminated by zero and you can walk with this notion: to zero. And so each string has at least one byte. In the case of other structures you need to know the size, as in the case of argv[] where the system gently gives you the argc.

However, the object to use malloc(), wouldn't it be because I don't know the total amount of >>elements?

I think you have understood the reason now: in the doubt between allocating thousands of records with the right size or thousands of records of the size of the largest record of all the option in general is to allocate all of the right size

 0
Author: arfneto, 2020-08-17 21:16:29