5

I have a question about how C function returns static variable:

in data.h file:

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

typedef struct
{
   int age;
   int number;
} person;

person * getPersonInfo();

in data.c

#include "data.h"
static struct person* person_p = NULL;

person * getPersonInfo()
{
   person_p = (struct person*)malloc(10 * sizeof(struct person));
   return person_p;
}

in main.c

#include "data.h"

int main()
{
   person* pointer = getPersonInfo();
   return 0;
}

function getPersonInfo() returns a pointer which is a static pointer in data.c, is this allowed and legal? in the main.c, can the function getPersonInfo() be used like this: person* pointer = getPersonInfo();

ratzip
  • 1,571
  • 7
  • 28
  • 53
  • [Do not cast the return value of `malloc()`](http://stackoverflow.com/a/605858/1983495), static in this context is related to the scope, the sotrage is always static for global variables. – Iharob Al Asimi Jun 03 '15 at 13:39
  • what does this mean "static in this context is related to the scope, the sotrage is always static for global variables" – ratzip Jun 03 '15 at 13:42
  • Using `static` inside a function means that the variable has `static` storage class, which causes that it preserves the value accross calls to the function, `static` at the file scope means that you cannot `extern`alize the variable/function to a different `.c` file. – Iharob Al Asimi Jun 03 '15 at 13:44
  • `static` keyword effects 2 things, visibility (depending on linkage) and lifetime.. Using `static` for a variable declared with global scope is redundant. – ryyker Jun 03 '15 at 13:45
  • yes, but the static variable is used to declare this variable is only visible in data.c – ratzip Jun 03 '15 at 13:47
  • 1
    function `getPersonInfo()` returns a pointer `person_p` holding value(value of return of malloc, side-effect assing to `person_p`). – BLUEPIXY Jun 03 '15 at 13:49
  • @BLUEPIXY sorry, can you explain – ratzip Jun 03 '15 at 13:50
  • function getPersonInfo() returns value of `person_p` (this value is copy on stack), isn't itself. – BLUEPIXY Jun 03 '15 at 13:51
  • Allowed and legal? Yes. Good programming practice? No. – Lundin Jun 03 '15 at 14:01
  • in this case, what is a good practice? In this particular example, what is a good practice to solve this problem? – ratzip Jun 03 '15 at 14:02
  • It is bad practice to return pointers to private variables. Also, with the current design, your .c file can only have one instance of the `person` object. Good practice would be to use opaque type instead. Move the struct definition to the .c file. In the h file, only have `typedef struct person person;`. All access to the members of this struct has to go through interface functions in the C file. I'd post an example but it would be off-topic since not related to the question. Feel free to post a different question and I can post an example. – Lundin Jun 03 '15 at 14:07
  • @Lundin Hi, I posted a new question regarding the good manner, can you give a example for this? http://stackoverflow.com/questions/30622741/return-pointer-from-a-c-function-is-good-bad-design – ratzip Jun 03 '15 at 14:18
  • @ratzip Roger that, I posted an example. – Lundin Jun 03 '15 at 14:44

3 Answers3

5

Line

static struct person* person_p = NULL;  

declares a variable person_p which has static storage duration, file scope and internal linkage. It means that it can be referenced by name only in file data.c and internal linkage restricts its sharing to this single file.

Static storage duration means once the memory is allocated to person_p it will stay at the same storage location as long as program is running, allowing it to retain its value indefinitely. It means you can return a pointer to that location.
Therefore, your code is valid and legal.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
haccks
  • 104,019
  • 25
  • 176
  • 264
  • 2
    but the pointer is defined as static, which is visible only in data.c – ratzip Jun 03 '15 at 13:40
  • Is this an answer to the post, or a comment to a specific follow-on question in the comments??? – ryyker Jun 03 '15 at 13:46
  • The question is about returing the pointer from a function. But the answer talks about returing a pointer to a static variable isn't it? Or am I not on track? – Gopi Jun 03 '15 at 14:01
  • @Gopi; Question asked by OP: *function `getPersonInfo()` returns a pointer which is a static pointer in `data.c`, is this allowed and legal?* – haccks Jun 03 '15 at 14:06
  • Yeah but my point was the location to which the static pointer is pointing to. OP does a malloc and return the address so that is valid is what I meant – Gopi Jun 03 '15 at 14:08
  • @Gopi; This question is all about static duration. – haccks Jun 03 '15 at 14:09
  • 1
    @ratzip, that `person_p` has internal linkage (as a `static`, file-scope variable) is not relevant to whether a function may return *a copy of its value*. It is the variable that is static, not its value. In fact, however, it would also be fine to return a pointer to the variable (`&person_p`), which is as close as you can come to returning the variable itself. – John Bollinger Jun 03 '15 at 15:15
1

person_p is a variable whose scope is just for the file data.c as it is a static variable. You are using this variable to allocate some memory on heap and return the address to main.c and there is a variable which holds this value in main.c i.e. pointer.

So here you are not returning the variable but the value the variable is holding which is totally fine because even if the variable goes out of scope the value returned(i.e. address) is still valid which is on heap.

Gopi
  • 19,784
  • 4
  • 24
  • 36
1

It is legal, as already noted in the other answers. You could even rewrite your data.c to this:

#include "data.h"
static struct person person;

person * getPersonInfo()
{
   return &person;
}

This will return a pointer to your structure in data memory, without any need to allocate it first on the heap. The static keyword is just about the scope of your symbol person (local to data.c) but the data itself is valid global in your program.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Sascha
  • 429
  • 2
  • 6