Gabriel
Gabriel

Reputation: 763

Passing by reference or use global variable in C

Which one is better if I want to modify the value into a function and bring it back to the main? And by saying passing by reference in C, I mean using pointers, like this example. Should I put 'a' as a global variable?

#include <stdio.h>
#include <conio.h>

int sum;

int example(int *a,int b)
{
    sum = *a + b;
    (*a)++;
}

int main(void)
{
    int a, b;
    printf("Tell me the value of A and B: \n");
    scanf("%d %d", &a, &b);
    example(&a, b);
    printf("The result: %d . And the new value of A: %d", sum, a);

    printf("\n\nTHE END\n");
    getch();
    return 0;
}

Upvotes: 3

Views: 9954

Answers (3)

dodgethesteamroller
dodgethesteamroller

Reputation: 1302

I find it helps to think of global variables as existing in a sort of special space outside the normal hierarchy of functions in a C program. If you drew a diagram with each function in a box, and lines between the boxes showing which function calls which others during the execution of the program, main() would be at the top (because it has no callers), and all other functions would appear below main() on one level or another, with lines leading to other functions above them.

Most data lives within only one function--inside a single box in the diagram. Some is passed from one function to another: most parameters and return values in a language like C would fit in this category. But global variables are "outside all the boxes"--in a place where any function can see and change them, and this "openness" makes them very dangerous--if any code in any function can change them, then it's very hard for you, or for other programmers working on the same code, once it gets to real-world size, to keep track of all the possible places where that global data could be changed. (This is the problem of "mutable state" that is common to programming languages in general, not just C, and which object-oriented and functional programming paradigms address to some extent.)

In your example, just the fact that you are asking the question

Which one is better if I want to modify the value into a function and bring it back to the main?

is a clue that this particular value should not be stored in a global variable. You have already conceptualized this particular piece of data as something that is shared between just two functions, main() and example(). Following the reasoning I gave above, that implies that the variable should be, if possible, passed as a parameter to example(), and then returned to main() via the return at the end of example(). Passing a pointer to a into example(), then modifying a inside example(), so that the change to a persists after control returns to the caller, is a perfectly ordinary idiom in C. But it needs to be documented carefully which parameters are subject to modification in this way, or else you quickly get into a situation like that with global data, only not quite as bad, where it's hard to keep track of where a might change and what it might change to.

This isn't to say that globals are all bad. They exist for a reason. If many parts of your code need read/write access to the same data, and efficiency is important, then globals may be the best way to accomplish that. In the environments where C code is most often run these days--"close to the metal," in embedded systems or driver code--there are often hardware resources such as registers or special-purpose memory that can most efficiently be accessed through a large set of globals. Or in some programs you might have a lot of state to keep track of--a whole set of variables whose values affect behavior throughout the program--and passing those values around is not just inefficient but makes the program less clear because you have the same set of many parameters being passed in to a large number of functions. (The classic example of this is a game, where the current state of the game world, the player's position, number of lives, etc. is relevant in some way to a majority of the code.) Even in these cases it's crucial that global variables be documented and named well so that they don't conflict with other similarly named locals or function parameters.

For a more advanced but related topic, see this answer for a brief explanation, or this page for a longer discussion, of how the scope (i.e., visibility) of a global in C can be restricted to a single source file with the static keyword, or shared across multiple files. This gives more fine-grained control over the accessibility of the global data and can help to alleviate some of the concerns with the free use of globals that I mention above.

Upvotes: 6

gnasher729
gnasher729

Reputation: 52538

The problem with a global variable is that there is only one. Once your code gets a bit more complicated, and starts using multiple threads, you run into the problem that there is only one global variable, and if the function is called from two threads, there is trouble because both calls use the some global variable.

Another problem with a global variable is that it needs a unique name. You called yours "sum". What are the chances that some time from now you will have other functions that add numbers and try to store them into a variable named sum? Again, you are in deep trouble. And if you manage to use different variable names, what are the chances that you pick the wrong one?

Use of global variables should be really limited. Use them only for things that are truly global, that is where it doesn't make any sense to ever have two in your application.

Upvotes: 4

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53006

In this particular case, the best thing to do is

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


int main(void)
 {
    int a, b;

    printf("Tell me the value of A and B: \n");
    if (scanf("%d%d", &a, &b) == 2) /* Avoid Undefined Behavior */
     {
        int sum;

        sum = example(a, b);
        printf("The result: %d . And the new value of A: %d\n", sum, a);    
        printf("THE END\n");
     }
    return 0;
 }

Of course, no real life program would have such function.

If the function is only modifying a int that is one more reason to avoid global variables, since you can return it from the function, and if it's a more complex situation, then you can return structs as well, and in the case it doesn't fit your needs you can pass/return pointers.

Upvotes: 0

Related Questions