Dynamic allocation with a void function

Asked

Viewed 176 times

0

I made a simple code using dynamic allocation. Just ask for the vector size, to insert data and print them at the end

I can make dynamic allocation with int, returning the vet, but as I’m learning, I’m trying to do some different things...

I don’t know if it’s too crazy that I try to do this. But you can explain to me why it doesn’t work?

void alocavet(int tam, int *vet){
    vet = (int*) malloc (tam * sizeof(int));
}

int main(){
    int *vet, tam, *p;

    printf("Tamanho do vetor: ");
    scanf("%d", &tam);

    alocavet(tam, vet);

    p = vet;

    printf("Entre com os elementos do vetor: ");
    for (int c=0; c<tam; c++) scanf("%d", &*p++);

    p = vet;

    printf("Elementos do vetor: ");
    for (int c=0; c<tam; c++) printf("%d ", *p++);
}
  • Did any of the answers solve your question? Do you think you can accept one of them? Check out the [tour] how to do this, if you haven’t already. You would help the community by identifying what was the best solution for you. You can accept only one of them. But you can vote on any question or answer you find useful on the entire site.

3 answers

4

Yes, it is absurd to do this. Even to learn it does not seem appropriate, because it is learning to do something wrong that should not be done. It’s even easier to do it the right way. And the fact that you did it the wrong way gave you room to get even more wrong since you didn’t release the memory. OK that this is just an exercise and will not cause any harm, the code ends soon and the memory is released by the OS, but gives the impression that never need and learn to do wrong. The same goes for checking if the allocation was successful, which is required in real code, but in exercise is ok.

The fact of having a function with no result return (void) It has nothing to do with that. It is rarely interesting to allocate memory within a function if you will need the data there where you call the allocator function. Always allocate where you will use the die. You can pass an allocation forward but not backward.

It is possible to do this as an abstraction, but you need to understand well what you are doing, which is not the case.

This case probably wouldn’t even need a dynamic allocation. It even needs it because it asks for a int, but is unlikely to allocate more than fits into a short, or even in a char. And this fits in the stack, therefore the allocation in the heap would be unnecessary. Ok, I understand it’s just for exercise, but it’s good to make it clear not to learn wrong.

It’s not the first time I’ve seen your code change the vector address instead of using an index. I mean, it’s not evolving, review the way you’re learning.

If you want to learn different things look for real different problems. Learning the error is learning, but learning wrong is not.

In this case there’s no need to do more than this:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int tam;
    printf("Tamanho do vetor: ");
    scanf("%d", &tam);
    int *vet = malloc(tam * sizeof(int));
    printf("\nEntre com os elementos do vetor:\n");
    for (int i = 0; i < tam; i++) scanf("%d", &vet[i]);
    printf("Elementos do vetor:\n");
    for (int i = 0; i < tam; i++) printf("%d ", vet[i]);
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

  • I did not understand why it is absurd a function [void] to make a dynamic allocation. Could you explain to me, please?

  • @slayerowner be voidis completely irrelevant, ignore the title in the question.

  • I don’t believe it’s irrelevant, because the void is a type of data that can be used to point to any other [data type] - as well as the NULL is to (void *)0. However, this would be the reason to cast in malloc(), since it is a function pointer of the type void.

  • @slayerowner no, you’re confusing things, one thing (void) has nothing to do with another (void *). Should not be done casting in the malloc(), this is a mistake made by beginners. And it remains irrelevant to her question, read the question and see if you find any relevance.

4

There’s no need to encapsulate the function malloc, even more this way, you could even get the return of it, however you would have to evaluate the gain and consider the context, but as it is learning you can use only malloc.

Below follows the code to allocate the memory block to the vetor, see:

#include <stdio.h>
#include <stdlib.h>

int main(void) 
{
  int i;
  size_t tam;
  int *vetor;
  printf("Tamanho:");
  scanf("%zu", &tam);
  vetor = malloc(tam * sizeof * vetor);
  if (vetor == NULL) 
    exit(EXIT_FAILURE);
  for (i = 0; i < tam; i++) 
    vetor[i] = i + 1;
  for (i = 0; i < tam; i++) 
    printf("%i\n", vetor[i]);
  free(vetor);
  return EXIT_SUCCESS;
}

Always remember to check the function return malloc, being NULL in the event of a failure to allocate, and in the event of address which points to the block allocated by the function. And when you finish using the variable allocated by the function use the function free() to de-locate the memory block that was previously allocated.

See working on repl it..

You have a question from me to respect of the subject.

Learn more about the malloc and the function free.

0


It’s no nonsense.

In function libraries, it is very common to have routines that take care of memory space allocation and misallocation, primarily for more complex structures.

What is wrong here is your understanding of pointer passing by function argument. I will explain.

In function main(), you declared a pointer vet for an integer, but this pointer has not yet been initialized:

int *vet, tam, *p;

Already the function alocavet() expects to receive the address of a memory space by means of a pointer, also named vet:

void alocavet(int tam, int *vet)

So you call alocavet() in main() and passes to the vet of alocavet() an invalid address, content that was there in the memory space of the uninitialized variable.

But that doesn’t matter much. Right in the first line of alocavet(), the invalid address received by vet is replaced by the address of the new memory space returned by malloc().

void alocavet(int tam, int *vet){
    vet = (int*) malloc (tam * sizeof(int));
}

When alocavet() returns, the pointer vet in main() keeps pointing to something, not yet initialized. And then, in the first loop, you use this invalid address in scanf, what makes the program break.

What happened to the allocation made by alocavet()?

It’s still there, but it lost the only reference it had. The pointer vet of alocavet() was destroyed when the function returned.

I know. You hoped that alocavet() would change the content pointed by vet of main().

One way to solve this is by using pointer:

void alocavet(int tam, int **vet){
    *vet = (int*) malloc (tam * sizeof(int));
}

In this way, vet of main() would continue to be stated in the same way, as a pointer to an integer:

int *vet;

And you would pass the address of this pointer vet using the operator &:

alocavet(tam, &vet);

This is enough to initialize the pointer on main() and, in addition, obtain the return of malloc(), to check if the allocation is unsuccessful, as said here, and also release memory after used.

Look how it turned out:

#include <stdio.h>
#include <stdlib.h>

void alocavet(int tam, int **vet) {
  *vet = (int *) malloc ( tam * sizeof(int));
}

void desalocavet(int **vet) {
  if (*vet) {
    free(*vet);
    *vet = 0;
  }
}

int main(){
    int *vet, tam, *p;

    printf("Tamanho do vetor: ");
    scanf("%d", &tam);

    alocavet(tam, &vet);

    if (vet == NULL) abort();

    p = vet;

    printf("Entre com os elementos do vetor: ");
    for (int c=0; c<tam; c++) scanf("%d", &*p++);

    p = vet;

    printf("Elementos do vetor: ");
    for (int c=0; c<tam; c++) printf("%d ", *p++);

    desalocavet(&vet);
}

Browser other questions tagged

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