Dynamic allocation in C - allocating without knowing the total amount of elements

Asked

Viewed 1,148 times

5

I have a question about the dynamic allocation in c, as to the use of the function malloc().

If we take, for example, a case of registration of a full name, as we have no way of knowing the amount of characters, we create the malloc(), thus, the field will adjust to 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;

I mean, in that case I’ll 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 be because I don’t know the total amount of elements?

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

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

char c[20]; 

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

The reason you have to use an allocation of type:

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

It would be because in C language, I need to know the size of my vector to get it runs 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;

That means I’ll be allocating 20 bytes (sizeof(char) * 20, considering the size of a char equals 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? There would be a waste in this case then?

3 answers

7


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

Generally no, it is common for you to set a maximum size that the name will have and allocate that amount. Eventually later optimizations can be made if necessary. You almost always choose whether you want to have the best memory consumption or the least processing possible.

It is possible to use a realloc(), but in most cases it does not compensate for the effort. It increases the allocation as needed, but 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;

I mean, in that case I’ll 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 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. Just this, you have to know the amount of bytes to be allocated.

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

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

Behold This prevents an array from being initialized with a variable size in C?. Or else How to store any string in C?.

And what is the size of char? 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 of 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 to the malloc(), not least because the malloc() also requires a known size. There is no magic, there is no elasticity. See What is the difference between vector pointer and variable pointer?.

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

In practice all allocation is done in execution. There is no allocation in compilation. There is defined allocation during the 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 at execution. Something like this is allowed:

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

The reason you have to use an allocation of type:

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

It would be because in C language, I need to know the size of my vector to get it runs the same?

No, that’s incorrect. Use it that way because you want the lifespan the object is detached from the lifetime of the function (the one in the automatic area) that created it, or you want to ensure that the size of the object does not create complicators for the stack which has a limited size, in which case you are assuring yourself because you know that potentially the object can be too big and even give a 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 for a variable with a very long name that must already be declared in advance. The rest is speculation.

That means I will be allocating 20 bytes (sizeof(char) * 20, considering that the size of a char equals 1), right?

Yes.

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? There would be a waste in this case then?

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

May be useful:

4

as we have no way of knowing the amount of characters, we created the malloc, so the field will adjust to 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 reserved space for 20 characters then you can only keep 20 characters.

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

That’s 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 in memory with a size of 34 bytes. Soon it is 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 to use dynamic allocation would be to make the memory space hold until it is done free. In contrast, in the static allocation that exemplified with char c[20]; at the end of the function this chars array is released and can no longer access it.

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? There would be a waste in this case then?

Use the first 10 and you still have to use one more for the terminator, otherwise you don’t have a properly completed string. The rest remain unused and have the value that was already in the memory, which in our eyes end up being randomized.

0

You’re right, but you’re wrong ;)

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

But you are perhaps summarizing the problem too much: following with your name example, let’s focus on city names and consider 4, with the number of letters between 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 you allocate memory for those names using what size? The size of the "largest" city, right?

char cidades[4][21];

For these 4 will be 84 bytes. However they only have 41 in total. With these 4 cities have already been 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 that area a structure is created as

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 finish the string.

Any resemblance to what the system does to every C program is because it’s 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 there are. And if you call your program x thus:

x azul 32 verde

your program gets

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

all strings with minimum size and terminated by zero.

I posted an example that does this for int**

It would be because in C language, I need to know the size of my vector for achieve the same?

In the case of a vector of char, to such a string, in C they are terminated by zero and you can traverse 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[] in which the system gently gives you the argc.

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

I think you’ve figured out the reason now: when in doubt between allocating thousands of records with the right size or thousands of records of the largest record size of all the option in general is to allocate all the right size

Browser other questions tagged

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