Function pointer versus global variable

New EE with very little software experience. Over the past couple of years I read a lot of questions on this site, this will be my first question / message. We did not find an answer for this.

I would like to know the difference / motivation between a function that changes a global variable in the body (without passing it as a parameter) and between passing the address of the variable.

Here is an example of each to make it more understandable. Let's say that I declare some functions of "peripheral.c" (with their corresponding prototypes in "peripheral.h" and using them in "implementation.c"

Method 1:

//peripheral.c //macros, includes, etc void function(*x){ //modify x } 

.

 //implementation.c #include "peripheral.h" static uint8 var; function(&var); //this will end up modifying var 

Method 2:

 //peripheral.c //macros, includes, etc void function(void){ //modify x } 

.

 //implementation.c #include "peripheral.h" static uint8 x; function(); //this will modify x 

Is the only motivation to avoid using a "global" variable? (Also, is it really global if it just has a file area?)

Hope this question makes sense. Thanks

+4
source share
6 answers

A function that takes a parameter that points to a variable is more general. It can be used to modify a global, local, or any variable. A function that modifies a global one can perform this task and only this task.

which should be preferred is entirely contextual. Sometimes one approach is better, sometimes another. It is impossible to say conclusively that one approach is always better than another.

As for the global global variable, it is global in the sense that there is one instance of this variable in your process.

+5
source

static variables are internally linked and cannot be accessed outside the translation unit in which they reside.

So, if you want to change the global static variable in another TU, you will need to pass it as a pointer through a function parameter, as in the first example.

The second example cannot work, because x cannot be accessible outside implementation.c , it should give you a compilation error.

Good reading:
What is external communication and internal communication?

+2
source

First of all, in C / C ++, “global” means the scope of the file (although if you declare a global header, it is included in files that # include this header).

Using pointers as parameters is useful when the calling function has some data that the called function should change, for example, in your examples. Pointers as parameters are especially useful when a function that changes its input does not know exactly what it is modifying. For instance:

 scanf("%d", &foo); 

scanf knows nothing about foo, and you cannot modify its source code to give it knowledge of foo. However, scanf accepts pointers to variables, which allows it to change the value of any arbitrary variable (the types it supports, of course). This makes it more reusable than depending on global variables.

In code, you usually prefer to use pointers to variables. However, if you notice that you are transmitting the same piece of information for many functions, a global variable may make sense. That is, you should prefer

 int g_state; int foo(int x, int y); int bar(int x, int y); void foobar(void); ... 

to

 int foo(int x, int y, int state); int bar(int x, int y, int state); void foobar(int state); ... 

Basically, use global values ​​for values ​​that should be shared by everyone in the file in which they are located (or files if you declare a global header). Use pointers as parameters for values ​​that must be passed between a smaller group of functions for sharing, and for situations in which there may be more than one variable with which you want to perform the same operations.

EDIT: Also, as a note for the future, when you say “function pointer”, people assume that you mean a pointer pointing to a function, and not passing a pointer as a parameter to a function, “Pointer as a parameter” has more meaning for what you ask here.

+1
source

A few different issues here:

  • In general, "global variables are bad." Do not use them if you can avoid this. Yes, it is preferable to pass a pointer to a variable so that the function can modify it than make it global so that the function can implicitly change it.

  • Having said that, global variables can be useful: use them by all means as necessary.

  • And yes, “global” can mean “between functions” (inside a module), as well as “between modules” (global throughout the program).

  • There are some interesting notes about your code:

    a) Most variables are allocated from the "stack". When you declare a variable outside a function like this, it is allocated from the "block storage" - space exists for the lifetime of the program.

    b) When you declare it “static”, you “hide” it from other modules: the name does not appear outside the module.

    c) If you want a truly global variable, you would not use the keyword "static". And you can declare it "extern uint8 var" in the header file (so that all modules will have a definition).

0
source

I'm not sure your second example really works, since you declared x as static (and thus limited its scope to a file), but at the same time there are some advantages of the pointer passing version:

  • This gives you more flexibility in distribution and modularity. Although there can only be one copy of a global variable in a file, you can have as many pointers as you want, and they can point to objects created in many different places (static arrays, malloc, stack variables ...)

  • Global variables are forced into each function, so you should always know that someone might want to modify them. On the other hand, pointers can only be accessed by functions that you explicitly pass to them.

  • In addition to the last point, global variables use the same scope and can clog too many variables. Pointers, on the other hand, have lexical scope like regular varialbes, and their scope is much more limited.


And yes, things can get a little blurry if you have a small offline file. If you are no longer going to create more than one "object", then sometimes static global variables (which are local to a single file) work just like pointers to a structure.

0
source

The main problem with global variables is that they promote what is called a "tight connection" between functions or modules. In the second design, the peripheral module knows and depends on the implementation design to such an extent that if you change the implementation by deleting or renaming x , you break the peripheral without even touching its code. You also cannot reuse peripheral regardless of implementation module.

Similarly, this construction means function in peripheral can only deal with one instance of x , regardless of what x represents.

Ideally, a function and its caller should communicate exclusively through parameters, return values, and exceptions (if necessary). If you need to maintain state between calls, use the record option to store this state, rather than relying on global.

0
source

Source: https://habr.com/ru/post/1416034/