Gonçalo Bastos
Gonçalo Bastos

Reputation: 421

Why do I need to return the pointer of a function

I haven't programmed with pointers for a long time and I do not remember when I need to return a char * or not! Let me make a example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/wait.h> 

void AllocMemory(char** buf);

int main(){
    
   char *array;

   AllocMemory(&array);

   printf("%s", array); //Printing and I dont make return
   
   free(array);

   return 0; 
}
    
void AllocMemory(char** buf){
    
    int bufSize = 10;
    int stringSize;
        
    *buf = calloc(bufSize, sizeof(char)); 
        
    if(*buf == NULL){
        printf("[ERROR] can't malloc %d bytes\n", bufSize);
        exit(1);
    }
    char *readpos = *buf; //point to a pointer of your array!
        
    while(1){   //looping until the alocated memory is enough to the inserted command

        do{

            fgets(readpos, bufSize, stdin); //reads a line from the specified stream

            stringSize = strlen(*buf); //getting the size of the array

            if (stringSize == 1)
            {
                printf("\nYou just pressed enter, pls type again: "); //checking if user just pressed enter
            }

        }while (stringSize == 1); //looping until user press only enter

    
        if (readpos[strlen(readpos)-1] == '\n'){ //Search from the end as there's where the newline should be if exists, the string fits on array and doesnt need to allocate more memory
                readpos[strlen(readpos)-1] = '\0';     //Remove \n from the string
                break;
        }   

        
        *buf = realloc(*buf, bufSize + stringSize * sizeof(char)); // Need to allocate more memory, because the before if its false
        if(*buf == NULL){
            printf("[ERROR] can't realloc more %d bytes\n", bufSize+stringSize);
            exit(1);
        } 

        readpos = *buf + stringSize; // Set the pointer to next position to read into 
    }
        
}

So in this case I think I don't need to return a char*, but sometimes I need to return it, I and I am wondering if its when its when the parameter is send as example:

char *examplefunc(char *buf){
   //Code here
}

So my question can be bad, but what I need to know, is when I need to return the char * or not!

void redirection(char** stringSplited, char** cRedirection, char** fRedirection){ 

   //I has splited the `stringSplited` here and save some parameters do `cRedirection and to fRedirection`and I do not need any return;
}

Upvotes: 0

Views: 102

Answers (2)

klutt
klutt

Reputation: 31379

It's always possible to change return value to output parameters. For instance, here are two functions that both add two numbers.

int add1(int a, int b) {
    return a+b;
}

void add2(int a, int b, int *output) {
    *output = a+b;
}

And then you invoke them just a little bit differently. But they work the same way.

int x, y;
x = add1(5, 6);
add2(5, 6, &y);

This is not different just because it's a pointer. A pointer is just a variable containing a memory address. The function realloc has this signature:

void *realloc(void *ptr, size_t size)

But that's just a design choice. This would work just as good:

void realloc(void *ptr, size_t size, void **output)

Or to put it in more general terms, this function:

T foo(<params>) {
    ...
    return <expr>;
}

can be converted to this:

void foo(<params>, T *output) {
    ...
    *output = <expr>;
}

The easiest way is to just write it as a wrapper:

void new_foo(<params>, T *output) {
    *output = old_foo(<params>);
}

Or vice versa:

T *new_foo(<params>) {
    T *ret;
    old_foo(<params>, ret);
    return ret;
}

My confusion was why I need to return a char* if I can declare it in function like this void examplefucn(char ** buf);

You don't have to.

Upvotes: 2

OctaveL
OctaveL

Reputation: 1045

Pointers are just a reference (address) pointing to some memory. If you pass char* to a function, then the function will be able to use it to change the content stored at this address ; and naturally, the address you pass hasn't changed, so you may use the pointer you provided even outside of that function.

You want to pass a char** when you want to modify a pointer itself and not the content it points to. In your example, you provide a char** to your AllocMemory() function, and it allocates memory at the address (which would be of type char*) pointed to by your double pointer buf. Returning anything is unnecessary, as you've modified the memory adequately, and so array in your main() will point to an address that has been initiated in your function. This address will point to the memory you initiated and manipulated in your function.

You're confused over whether or not to return values because you don't seem to fully grasp how pointers work - understandably so, it's an unintuitive idea. But if you understand what you are accessing and the difference between a pointer char* and a pointer to a pointer char**, then you'll know when you want to return a pointer and when it's unnecessary. It depends on the context, and it's unnecessary in this case.

Upvotes: 1

Related Questions