Update (int) variable in C inside a function [duplicate] - c

This question already has answers here:
How to change a variable in a calling function from a called function? [duplicate]
(3 answers)
Closed 8 years ago.
I'm trying to write a function that changes screen in my simple C snake game.
main(){
int stage = 0;
...
..
.
while(stage!=0){
//if snake hits wall
changeStage(stage);
}
}
function:
void changeStage(int stage){
stage = 1;
}
This code does not update the code, it will keep on running.
What is wrong with my code?

stage is passed by value to changeStage. stage = 1 only changes the local value of stage in changeStage, not the value of stage in main. You have to pass a pointer instead:
while (stage != 0) {
changeStage(&stage);
}
void changeStage(int *stage) {
*stage = 1;
}

C is a pass by value language. The simplest approach to accomplish what you want is to pass a reference to the variable you need to change. For example:
void changeStage(int *stage){
*stage = 1;
}
main(){
int score = 0;
int stage = 0;
...
..
.
while(stage!=0){
//if snake hits wall
changeStage(&stage);
}
}
Note: You may need to read up on pointers to fully understand the code if you are just beginning with C programming. In the example code, instead of passing the value of 'stage', you pass the location where the value of 'stage' is stored. The function can then modify the contents in the location.

C function arguments are pass-by-value. This means that instead of passing a reference to stage you are passing the value stored in it. The update you do the in changeStage function then only applies to the copy that has been made.
If you want to update a variable in another function, you will need to pass a pointer to it.
void changeStage(int* stage_p){
*stage_p = 1;
}
int main() {
//...
while(stage!=0){
//if snake hits wall
changeStage(&stage);
}
}
&stage says to take the address of stage and pass that to the function. The stage_p argument will then point to the int in the main.
*stage_p causes it to use the value pointed to by stage_p, which is stage in the main in your case.
Further reading

You are not modifying the original stage variable, but only modifying an local copy inside changeStage function.
You need to use a pointer:
void changeStage(int* stage)
{
*stage = 1;
}
using the function:
while (stage != 0)
{
// if snake hits wall
changeStage(&stage);
}
You need learn more basic concepts of C language. Pointer is an very important feature in C language.

Correct, you need to pass the pointer if you wish to change the value of the variable in main() or you can create it as global variable, that way it's accesable both in functions and in main.
static int stage = 0;
void changeStage(){
stage = 1;
}
main(){
int score = 0;
...
..
.
while(stage!=0){
//if snake hits wall
changeStage();
}
}

Related

Calling a function without losing that data that the function had before?

I picked up the bad habit of Global Variables early on, So ive been trying to distance myself by using local variables and learning call by reference/value which isn't so bad until I run into a problem like this, say I have a function Menu() which contains a main menu, and an array, then from the Menu I'd go to a function and do stuff with the Array, now I usually get stuck here my functions are usually of void type, but usually for my programs I use a if selection to get back to the Menu, like If(userinput ==2){Menu();} usually this causes two problems 1. When I enter Menu it resets all the variable values
2.If i have this function in multiple places it will start giving me parameter errors.
These problems discourage me and make me lean towards the side of Global Variables.
Example:
menu(){
int array[100];
functionadd(array);
}
functionadd(array[])
{
int userinput;
do{
//lets the just say here the program does things to my array.
// usually when I want to go back to the menu I'd do something like this
printf("Again or back to menu?1(Again) or 2(Menu)")
scanf_s("%d%[^\n]", &userinput); '\n'==getchar();
} while(userinput == 1)
if(userinput != 2){Menu();} /*this would bring me back to
the menu but my array would be back to as its original state
when it was called in Menu I understand why this happens I
just need to learn how to counter act it*/
}
Some pseudo code to not have a variable to be "reset" with static keyword:
int Menu(){
static int remember = 0;
remember++;
return remember;
}
int main(){
printf("remember = %d\n", Menu());
printf("remember = %d\n", Menu());
printf("remember = %d", Menu());
}
output:
remember = 1
remember = 2
remember = 3
Notice that a global variable is, like Ron says, is a variable for the lifetime of the program. So is a static variable, but in this case it isn't accessible in another function. Also, a static variable isn't really thread safe
"All non-local state must be accessed through atomic operations and
the data-structures must also be reentrant."
Well, You're calling is something like this:
main()
{
menu();
}
menu()
{
yourfunction();
}
yourfunction()
{
if(userinput==2)
menu();
}
Here, you can observe that you're again calling menu() but not returning back..
If you're at the depth in menu(), if you'll exit, will return to yourfunction() but not the main().
I'll recommend you to use codes similar to the following:
menu()
{
do
{
yourfunction();//call your function
//after the completion ask to continue
printf("Do you want to continue? (Y/N) ");
fflush(stdin);
scanf(" %c",&choice);
}while(choice=='y'||choice=='Y');
}
void yourfunction()
{
//do only functional job
}
This will help you to return to the menu() and ask you for the continuation.
And also the values will remain as you want them to.
Edit:
Or if you want to stick to your habit of programming.
Simply tell the program what to do when user input is 1 (i.e. not equal to 2)
And don't define anything when 2 is input.
It will automatically return to menu()
menu()
{
yourfunction();
}
Yourfunction()
{
if(userinput==1)
{
// do this
}
}
Or other way:
menu()
{
yourfunction();
}
Yourfuntion()
{
if(userinput!=2)
{
//do this
}
}
If the function gets userinput as 2 it will get back to menu().
Over.. :-)
If you save a variable like static you'll not lose the data the function had before, cause the variable won't be destroyed at the end if the function and the stack won't be cleaned. Example:
static int var=0;
var++;
return var;
If you call the function 10 times the variable will be increased ten times.
You should take note of the following:
In C, all parameters are passed using call by value.
When you passing an array as parameter to a function, it decays as a pointer to the first element of the array.
Call by value doesn't mean you can't modify some function's local variable from another function. For that, you pass a pointer as parameter and then from the callee function assign value to its dereferenced stated.
eg:
void f(int *c)
{
*c = 7;
}
int main(void)
{
int count = 4;
f(&count);
printf("%d", count);
return 0;
}
The reason people discourage overuse of global variables is because those variables will be taking memory for the life of the program (process really).
But, in this specific case, that's the behavior you want. You want to remember the state of the menu between calls, and you can either implement a structure yourself and save the state in the calling function, or you can simply declare the variable globally.
What irks people is when every variable is global, regardless of whether they need to be. In a language like C, which basically only survives because of its ability to manually manage memory to the utmost efficiency, it hurts our brains to see people wasting it. In general, it's a code smell to see any global variables that aren't constants. As a commenter has pointed out, there are other reasons to avoid using globals. Rather than iterate through them all, I'll leave this here: why globals are bad
Note, I'm not trying to be mean, just not sure which of those pages is the best resource, so I gave OP all of them.
Edit: a few other points. You also could easily accomplish what you need by either passing a pointer containing the value you may or may not edit within the function as a parameter, but the solution I would probably implement given what you've said is like this:
int choice = menu();
case (choice ):
//logic here

Unable to modify pointer variable passed as argument to a function

I have this function
int rt_exist(struct route_entry* prev_rte) {
prev_rte = rte_head; //This doen't assigns rte_head to prev_rte
return 0;
}
where rte_head is an initialized struct route_entry* pointer variable.
But in the above case "prev_rte" is not assigned the value of rte_head.
By the way ,I if I do something like this
int rt_exist(struct route_entry* prev_rte) {
struct route_entry* rte_new;
rte_new = rte_head; //But this can
return 0;
}
The above assignment occurs smoothly . The problem arises when pointer variable is passes as function argument.
It's a weird question with little details ,but can someone point me to a possible direction or something wrong I might be doing.
Consider this:
void foo (int j)
{
j = 7;
}
foo (8);
What do you expect to happen here? A function can't change a value in the caller this way.
What should happen here:
rt_exist (NULL);
For C++, you can use references:
int rt_exist(struct route_entry*& prev_rte) {
prev_rte = rte_head; //This doen't assigns rte_head to prev_rte
return 0;
}
For C, you need to pass a pointer to the thing you want to change:
int rt_exist(struct route_entry** prev_rte_ptr) {
*prev_rte_ptr = rte_head; //This doen't assigns rte_head to prev_rte
return 0;
}
Yes! in first case you are using temporary portion of a stack. But in the second case you are using allocating. Which means that you are using a portion of memory which is from heap. It will obviously affect the value. This is like a new variable in a new block. In this scope it will have the assigned value.
But in rt_exist the copy of the variable is passed. So any change in that will not affect the actual one. But you can pass it's address and change it easily like this.
int rt_exist(struct route_entry** prev_rte)
{
*prev_rte = rte_head; //This does assign rte_head to prev_rte.
return 0;
}

How do you properly allocate a struct inside a function? [duplicate]

This question already has answers here:
How to malloc inside a function and return pointer in C?
(3 answers)
Closed 7 years ago.
I have this code which is where I've narrowed down the problem. When I step through with the debugger it seems to be fine but as soon as it leaves the function, freeCount loses the value assigned to it. It is supposed to be 100, and until the last } it shows it assigned the value fine but as soon as the function breaks it goes back to some 16 digit value. Can anyone point out my error?? much appreciated!
void initializeTree(TREE* empList)
{
empList = (TREE *)malloc(sizeof(TREE));
int i;
for (i = 1; i <= maxEmp; i++)
{
time_t seed = time(null);
empList->freeList[i] = (int)(rand() % seed);
}
empList->freeCount = maxEmp;
empList->parent = null;
empList->root = null;
}
It's because in C arguments to functions are passed by value, which means they are copied. So when you pass a pointer to a function, the functions receives a copy of the pointer, and as you know changing a copy will not change the original.
C doesn't have argument passing by reference, but it can be emulated using pointers. So to pass a pointer by reference you need to pass a pointer to the pointer.
void initializeTree(TREE** empList)
{
*empList = malloc(sizeof(TREE));
...
(*empList)->freeCount = maxEmp;
...
}
To call this function you need to use the address-of operator &:
TREE *empList;
initializeTree(&empList);
Another alternative is to return the pointer:
TREE* initializeTree(void)
{
TREE* empList = malloc(sizeof(TREE));
...
return empList;
}
You are overwriting the value of empList in your function but it does not reach the caller. What you actually need to do is to pass in a pointer to a pointer of tree:
void initializeTree(TREE** empList)
{
*empList = (TREE *)malloc(sizeof(TREE));
[...]
}
You can also find more information (and other options) here.

C - pointers when new functions are called [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Say I have something like:
function2(int *hello) {
//something
}
function1(int *hello) {
function2(&hello);
}
void main() {
int hello = 0;
function1(&hello);
}
How do I make it so that function2 can change the original value declared in main?
Change this code:
function1(int *hello) {
function2(&hello);
}
to:
function1(int *hello) {
function2(hello); // <-- no "&" in this call!
}
Then you can do this:
function2(int *hello) {
*hello = 123; // <-- dereference pointer hello
}
You are making a mistake in the function1 where your pass the address of the pointer to your int hello in the main function. you pass the pointer forwart to the function2 and the dereference it in there.
function2(int *hello) {
*hello = 123 ;
}
function1(int *hello) {
function2(hello); //pass the pointer on to function2
}
int main( void ) {
int hello = 0;
function1(&hello);
return 0 ;
}
You are also incorrectly declaring your main function. It should be declared as int main() with a return statement.
As mvp reply it is correct answer but i am here just explaining something, which will help you to understand, why your code is not working.
First let me explain operator you used
1] Ampersand Operator (&)
This operator helps you to get reference/address of variable
As soon as we declare a variable, the amount of memory needed is assigned for it at a specific location in memory, As we generally do not actively decide the exact location of the variable within the operating system during run time but some time we need to know address of our variable like here You want to know the address of variable to assign it's address to pointer The address that locates a variable withing memory is what we call a reference to that variable Which we can get using Reference variable.
Dereference Operator (*)
As we know that pointer is the variable which will store that address of the another variale, using pointer we can directly access the value stored in the variable which it points.To do this we simply have to precede the pointer's identifier with an asterisk (*), which acts as deference operator and that can be literally translated to value pointed by
Now back to your code
function2(int *hello) { // Here you create function that accept address of variable (You will get address of hello pointer 101 NOT 100 of variable assign in your MAIN)
//something
}
function1(int *hello) {// Here you create function that accept address of variable (Here it will get address of hello which is 100)
function2(&hello); // Here you again pass address of your pointer hello (Which may be 101) [BAD]
}
main {
int hello = 0; // Let say it's address is 100
function1(&hello); // Here you pass address of your variable(which is 100) [GOOD]
}
Solution is as suggested
function2(int *hello) {
//Change your value here
*hello = 123;
}
function1(int *hello) {
function2(hello); // It will pass 100 (address of your variable hello assign in MAIN
}
main {
int hello = 0;
function1(&hello);
}
The "&" operator means "address of", so your function 1 is trying to call function2 with the address of "hello" rather than the address hello contains.
Responding to a different question I said this:
Pointers are variables which store a number, like any other, but because you tell the compiler it is a pointer, the compiler allows you to use that value as an address of things in memory and the language provides "dereferencing" as a way of saying "the value AT the address this variable describes".
Imagine you're going to the airport to catch a flight. You grab a post-it note and write down your flight number, and you take a second post-it with you for your gate.
The first post it is a "flight*" pointer and your second is a "gate*" but right now the gate* pointer is empty.
When you get to the airport, you look up your flight on the board and jot down the gate number. "3A". Now your gate* post-it is valid.
But the post-it itself is NOT your gate, it just points to it: you still have to "dereference" the post-it note to get to your flight - that is, walk across the airport to gate 3A :)
When you called function1 you took the address of the variable in main. All you need to do is forward it to function2. What your code was trying to do was make a note of which post-it not the gate number was on, rather than just looking at the post-it note.
Solution
#include <stdio.h>
void function1(int*); // so the compiler knows what the function looks like.
void function2(int*);
int main() {
int varInMain = 0; // lets call it something distinct
printf("varInMain starts with %d, it's location in memory is %p.\n",
varInMain, &varInMain);
function1(&varInMain);
printf("varInMain is %d after calling function1.\n", varInMain);
return 0;
}
void function1(int* func1ptr) {
printf("function1: func1ptr points to memory location %p, which contains %d.\n",
func1ptr, *func1ptr);
*func1ptr = 1010;
function2(func1ptr);
}
void function2(int* func2ptr) {
printf("function2: func2ptr points to memory location %p, which contains %d.\n",
func2ptr, *func2ptr);
*func2ptr = 123;
}
You can see a live demo of this code on ideone.com here.
Output looks like this:
varInMain starts with 0, it's location in memory is 0xbfef2fdc.
function1: func1ptr points to memory location 0xbfef2fdc, which contains 0.
function2: func2ptr points to memory location 0xbfef2fdc, which contains 1010.
varInMain is 123 after calling function1.

How to manipulate the Global Variable in C

I have multiple void functions that relies on the each individual output of the functions since there are multiple variables (that are the same throughout the code), where each functions' output will be "stored" to them and be passed to another.
So, I decided to make those variables into global variables by making them static .... right after all the necessary #include... codes.
I was able to utilize all functions (14 functions in total,all void) by only calling four of them (Each functions, after processing its own function, passes the result into another function and after series of passing, only four of them are needed to be called in int main())
Now, I created another void function that requires the global variables as its parameter since that void function relies on the data that all the other functions "copied and put" into the global variables declared earlier. (Which I found is not working, since I heard that storing data into global variables is not possible.)
Can anyone teach me if there is any other way to create series of functions which requires output of each individual functions?
I checked if the variables were stored properly, so I tried using printf method right after the #3 process. I found out nothing gets printed when I expected a value from the struct data to be printed.
Ex:
typedef struct database{
//... variables
}data;
typedef struct itembase{
//... variables
}item;
static data user1;
static data user2;
static data *pointer[10000];
static item *pointer2[10000];
static item current[10000]; //Shares same value of the bracket with *pointer2
static data sectionA[1][10000];
static data sub_section[3][10000];
static int datacounter = 0; //..will be put inside the bracket of *pointer
static int itemcounter = 0; //..will be put inside the bracket of *pointer2
static int typenum = 0; ..will be put inside the first bracket of all the sections and subsections
static int section_count = 0; //..will be put inside the second bracket of all sections
static int sub_section_count[3] = {0}; //..will be put inside the second bracket of all sub_sections. The [3] will be the value of the typenum.
void load_data() // Accepts User's input and store them into struct data's variable using singly-linked list
{
//.... All data will be stored to *pointer[datacounter]
binarycheck(pointer[datacounter]->encoding,*pointer,datacounter);
//.... The `typedef struct` of data contains 12 variables. After storing 12 variables, datacounter will be ++ and the program will still continue to accept input from the user
}
void load_item()
{
//.... All item will be stored to *pointer2[itemcounter]
memcpy(&current[itemcounter],pointer2[itemcounter],sizeof(item));
}
void binarycheck(data encoding,data *pointer,int datacounter)
{
if ((encoding&128)==128){
typenum = 3;
memcpy(&sectionA[typenum][section_count],pointer,sizeof(data));
sub_sectionA[typenum][sub_section_count[typenum]] = sectionA[typenum[section_count];
section_count++;
sub_section_count++;
}
}
void askitem(data user)
{
// Tried putting `printf(" %s User1 Data#1",user1.firstdata);` and it works perfectly fine.
// Ask for user's selection on item
// If the item is found, then the content of that item will modify the data of the variable of `user`
}
void askinput(data user)
{
int whattype = 0;
int whatsub = 0;
printf("What type do you want?: \n);
scanf("%d",&whattype);
if (whattype == 1)
{typenum = 1;}
printf("What Sub type do you want?: \n);
scanf("%d",&whatsub);
if (whatsub == 1)
{ user = sub_sectionA[typenum][sub_section_count[typenum]];}
askitem(user);
}
void final_print(data user, data user2)
{
printf("%d\n",user.Adata);
printf("%d\n",user2.Adata);
}
int main()
{
load_data();
load_item();
askinput(user1);
//Tried putting `printf(" %s User1 Data#1",user1.firstdata);` but nothing shows.
askinput(user2);
//Nothing shows
final_print(user1,user2); //Nothing shows
}
Take a look at this function:
void askinput(data user)
Here you pass user by value to the function. When you pass by value, the function receives a copy of the variable. Changes that you make inside the body of that function only affect the copy. They are not visible to the caller's variable.
Instead you need to pass a reference. In C that means passing a pointer to a variable:
void askinput(data *user)
Inside the body of the function you need to de-reference the pointer to access members. So you use -> rather than . to refer to members.
And when you call the function you need to pass a pointer to the variable. So the call becomes:
askinput(&user1);
Frankly I do not understand why you are using global variables here at all. It's generally preferable to pass parameters otherwise you do find yourself struggling to keep track of which different version of the variable you are meant to be working on.
Finally, you have written your entire program and trying to debug this specific problem in the context of the entire program is confusing you. You really should have cut this down to a 10 or 20 line simple reproduction. Being able to do that in the future will make life much easier for you.

Resources