understanding pointers in functions (referring values) - c

int func (int a, int b, int *c);
int main()
{
int res, x, y, z; //int res, x, y, *z;
printf("enter x \n");
scanf("%i", &x);
printf("enter y \n");
scanf("%i", &y);
res = func(x, y, &z); //res = func(x, y, z);
printf("result addition: %i, result multiplication %i \n", res, *z);
return 0;
}
int func (int a, int b, int *c)
{
int result;
result = a +b;
*c = a*b; //(1) alternative:d=a*b
// c=&d
return result;
}
My problem is, that i don't understand, why this code doesn't work when i write it as i like i did in the comments (//) . Compiler warns me, that z is not initialised, but why isn't that a problem in the working version?
Another thing i don't understand is, why it's correct to refer pointer a value like i did it in (1) but it's wrong in the following code:
int main()
{
int a, *c, *d;
scanf("%i", &a);
*c=a; //wrong
d=&a; //correct
return 0;
}

Compiler warns me, that z is not initialised, but why isn't that a problem in the working version?
The compiler warns you about z being uninitialized because you're passing it by value. And what you're passing is an uninitialized value (which is basically garbage).
It doesn't warn you when you pass the address of z because there's nothing wrong with passing the address of a variable to a pointer. The compiler doesn't check whether you're going to dereference c and use the uninitialized value of z. The compiler's just not that "smart". It assumes you'll do the right thing and just assign z a value by dereferencing c (which you indeed did).
why it's correct to refer pointer a value like i did it in (1) but it's wrong in the following code
As for your 2nd question, the first example works because the parameters of the functions get initialized to whatever values you called the function with.
The 2nd example doesn't work because you're using uninitialized local variables.

At the point where a variable is declared, it comes into existence at some memory location that can be retrieved with &, whereas (if you don't initialize it) the contents of that location is uninitialized. When z is an int, &z is a well-defined pointer because it is the address of a variable, not the contents of one. When z is an int *, z's content is itself a pointer, but it's not initialized; hence the warning (and most likely, your program will crash when scanf() attempts to write to an arbitrary memory location).

your question implies that you have no knowledge about pointers, I suggest you read about them first,
a pointer points to a variable, when you do
*c = a
you are trying to assign a value to the variable pointed to by c with the indirection operator '*',
the problem is that c is not pointing to anything in your code.
in the second one
d = &a;
you make the pointer d point to a. In other words you assign d the address of a. You really should read about pointers first otherwise, whatever we say here will not make sense to you.

Related

Why does global pointers behave erratically in this function?

I've tried to write a program that uses global pointers to track down local variables, but when I use the right syntaxes, it doesn't run.
When I alter the syntaxes, the program yields correct results. I don't fully understand the mechanism behind it, and hoping that more experienced coders could explain it. Thank you.
#include <stdio.h>
#include <math.h>
int *q;
int *u;
int *p;
void test () {
printf("Insert #1?\t"); scanf("%d", &u);
/*should be scanf("%d", u) for u is a pointer*/
printf("Insert #2?\t"); scanf("%d", &p);
/*should be scanf("%d", p) for p is a pointer*/
}
int main () {
test ();
printf("%d\n", u);
/*should be printf("%d\n", *u) since I am trying to dereference the value of u*/
printf("%d\n", p);
printf("%d\n", q);
}
The output should be 3 numbers, 2 first numbers are inputs from user, and the third one should be a nonsense number since the 3rd pointer is not pointing anywhere.
Update: It works!!!!! Thank you so much for your help :).
This has nothing to do with global variables. There are multiple problems here but the most pressing error is that you are attempting to use uninitialised pointers. This never works. You need to understand pointers before you can use them properly.
In particular, if you have a declaration like this:
int *x;
Then, no matter what you do, you first need to assign a valid pointer to x1.
In your case the error is compounded by the fact that you’re using scanf wrong. Luckily the solution here is very easy: Don’t declare pointers. Instead, declare int variables.
#include <stdio.h>
int q;
int u;
int p;
void test () {
printf("Insert #1?\t"); scanf("%d", &u);
printf("Insert #2?\t"); scanf("%d", &p);
}
int main () {
test();
printf("%d\n", u);
printf("%d\n", p);
printf("%d\n", q);
}
Ironically the comments in your original code already point out the issue, they just suggest a wrong solution. It’s a bit of a mystery where these comments are from. ;-)
1 Technically the only exception is for statically allocated pointers, which are correctly zero-initialised and can therefore be used in null pointer comparisons.
Your global variables are the pointers to the ints, not the ints themselves. When you read in the values, you change where in memory u points to, not the value of u.
You should replace it with either scanf("%d", u); or change the declaration to int u.
You need to be careful taking pointer values from the user. Otherwise, you could risk things like null pointer dereferencing. For instance, Entering 0 when you scanf("%d", &u);, it would then make the value of u be NULL.
As I said in my comment to the question, a pointer is a type that holds the address to another variable of some type, so int* holds an address for a variable of type int. In your case, &u is referring to the address of u, so you're trying to scan a number into a pointer which won't work. You should change it to only u so it will scan to the variable it points too, but it needs to point to a valid variable in the first place. Here is a valid example:
int someNumber = 5;
int* u = &someNumber; // u points to a valid address statically allocated
scanf("%d", u); // Scans the number inputed to someNumber because u points to it
getchar(); // Avoid buffer overflow
printf("%d\n", *u); // A * dereferences u - gets the value of the variable it's pointing to
Pointers need to point to something, such as another variable, or memory allocated dynamically with malloc().
You can't use scanf() to read directly into a pointer. You can use it to read into what the pointer points to.
So you can write something like this:
#include <stdio.h>
#include <math.h>
int q;
int *qp = &q;
int *up;
int p;
int *pp = &p;
void test () {
printf("Insert #1?\t"); scanf("%d", up);
printf("Insert #2?\t"); scanf("%d", pp);
}
int main () {
up = malloc(sizeof(*up));
test ();
printf("%d\n", *up);
printf("%d\n", p);
printf("%d\n", q);
}
Your pointers have no value assigned to them.

What is the difference between referencing pointers in a function

I'm creating a function which modifies a variable so it can be used by the function referencing it (parent function?).
Is there a difference between using '&x' compared to using 'z' in the code below?
void changeX(int *p);
int main(void) {
int x = 10;
printf("%d\n",x);
int *z = &x;
changeX(z);
printf("%d\n",x);
// or
changeX(&x);
printf("%d\n",x);
return 0;
}
void changeX(int *p){
*p = *p + *p;
}
wildplasser made a good point, updated to show where I have gotten each value in the output.
Output is:
10
20
40
Both produce the same outcome (change x in the same way), but is there a non-obvious difference between them?
Thanks for the answers in the comments. It makes sense to me now.
The first call initializes the parameter from the argument z, i.e., the value of the argument is the value of the pointer z, which was initialized to be &x, a pointer value that points to the object x. The second call initializes the parameter from the argument &x, which is a pointer value that points to the object x. There is no functional difference between the two calls. In both cases, the parameter p in the function will have the exact same value, a pointer value that points to x, the only difference is where that value came from at the point where function was called…

In the following program the invocation of change_it() seems to have no effect. Please explain and correct the code? [duplicate]

This question already has answers here:
How to change a variable in a calling function from a called function? [duplicate]
(3 answers)
Closed 4 years ago.
void change_it(int[]);
int main()
{
int a[5],*p=1;
void change_it(int[]);
printf("p has the value %u \n",(int)p);
change_it(a);
p=a;
printf("p has the value %u \n",(int)p);
return 0;
}
void change_it(int[]) {
int i=777, *q=&i;
a = q; // a is assigned a different value
}
For starters, when you initialize p, you're giving a pointer the value of 1, when it needs a memory location. NULL uses 0, but that doesn't mean you can -or should- just assign integer values to pointers.
Just as an fyi, you can cast the value of 1 like this:
int a[5], *p = (int *) 1;
There's like -2 reasons for doing this, though, the -1th reason being that the minimal type safety that C provides should be respected, and the -2th being that it makes the code hard to understand for other people.
I'm going to assume what you meant to do was not declare a pointer with an address value of 1 though, and say you meant to declare a pointer that holds a value of 1. Unless you have another variable that holds the value of 1 already, you're going to have to first dynamically allocate the pointer, then set its value.
int* p = malloc(sizeof(int));
*p = 1;
If you had another variable to use, you could instead create the pointer on the stack rather than dynamically allocating it, like this:
int* q;
q = p;
Now, calling the same print function on both would yield this:
printf("p has the value %d\n", *p);
printf("q has the value %d\n", *q);
Output:
p has the value 1
q has the value 1
Addressing your main problem, you need to name the parameter in the change_it function, for example:
void change_it(int arr[])
Your program needs the parameter to be named, otherwise it has no idea of knowing you're trying to reference the array. The a variable you reference in the function is not bound to anything; the compiler will know be able to deduce what you're talking about.
Also, you don't need to redeclare the function prototype in your main function. The reason this is not a compiler error is that you can have as many declarations as you want, but only one definition. Again though, there's no reason to do this.
Another fyi, you don't have to name the parameters in your function prototypes, but it's good practice to both name them and be consistent with the names between the prototypes and the actual implementations so that people reading your code understand what's going on.
Also, you're using the %u specifier for the printf function, when you're not actually using unsigned decimal numbers. You're using signed decimals so you should use %d.
Lastly, your change_it function commits one crucial error preventing it from correctly changing the value of the passed-in array properly: you're setting the array that you passed in to the value of q.
Look at the function in your original code closely (pretend you named the input array a, as it looks like you mean to). You first declare an integer variable i and set its value to 777. Then, you create an integer-pointer variable q on the stack and correctly set its value to i. Note: You're not setting q to the value of i, but rather the address of i.
Why does this small but significant distinction matter? When you set a to q in the next line, you're changing the address of the array, specifically the first element of a five-element integer array, to point to the address of an integer variable. This is bad for a few reasons. First, the array is five integers long, but now it points to a single element. If and when you try to access elements 2-5, you'll get either meaningless garbage or a segmentation fault for trying to access memory you don't own. Even worse, the variable i is allocated on the stack, so when the function change_it exists, the function's data will be popped off the stack, and trying to access the address of i will yield either garbage or a segmentation fault for trying to access memory you don't own. See a pattern?
I'm not really sure how to correct this code, as I'm not sure what you were trying to accomplish, but correcting the aforementioned errors, your code now looks something like this:
#include <stdio.h>
void change_it(int arr[]);
int main()
{
int a[5];
int *p = a; // Equivalent to int *p = &a[0];
printf("a address: %p\n", a); // Should be equal to p
printf("p address: %p\n", p); // Should be equal to a
a[0] = 1;
printf("a[0] = %d\n", a[0]); // 1
printf("p has the value %d\n", *p); // 1
change_it(a);
p = a;
printf("a address: %p\n", a);
printf("p address: %p\n", p);
printf("a[0] = %d\n", a[0]);
printf("p has the value %d \n", *p);
return 0;
}
void change_it(int arr[])
{
int i=777;
arr[0] = i;
// Could be just:
// arr[0] = 777;
}
Output:
p address: 0x7fffc951e0b0
a[0] = 1
p has the value 1
a address: 0x7fffc951e0b0
p address: 0x7fffc951e0b0
a[0] = 777
p has the value 777
Note: Your memory address can and probably will be different from these, all it matters is that p and a are equal in both.
Anyways, hope this helps. Let me know if you have any questions.
Alright, you I believe do not have basic understanding of a function: First lets start with declaration and definition:
void change_it(int[]); // THIS IS DECLARATION
int main ()
{
void change_it(int[]); // THIS IS DECLARATION (duplicate and unnecessary
....
}
void change_it(int[] a) // THIS IS DEFINITION
{
int i=777, *q=&i;
a = q; // a is assigned a different value
}
declaration of the function only needs (you can put parameter name for readability) a parameter type, where as definition has to have name of the parameter because in definition parameters are local variables.
printf("p has the value %u \n",(int)p);
This will print the address of p not the value of p. So this should be
printf("p has the value %u \n", *p);
And finally we get to the body of a function. Where you are depending on somthing that have been locally assigned and putting it back into parameters
void change_it(int[] a)
{
int i=777, *q=&i;
a = q; // a is assigned a different value
}
so q is pointer and you are assigning address of local variable i to it. Well what happens when your program exists the function? i might disappear thus loosing its values and its address, which is assigned to q which means q is loosing its variable and value, and which is assigned to a which might loos its variable because it is pointing to i in your function.
This part here:
int a[5],*p=1;
void change_it(int[]); // Here, doesn't compile
printf("p has the value %u \n",(int)p);
That statement isn't just valid, as far as I know, you can't declare a function inside another function in C.
Also:
void change_it(int[]) // Here, an error
{
int i = 777, *q = &i;
a = q;
}
This function needs an argument, but you supplied only its type (being int[]),
void change_it(int a[]) fixes the problem
Your program does not compile and produce warnings. It would not work as you intended.
1) p is a pointer. To access value which it points to you have to dereference it using * dereference opearator.
2)
void change_it(int[]);
is not needed in the body of main.
3)
the invocation of change_it() seems to have no effect
If you want to change a[0] element inside the function change_it name the passing parameter to a and dereference the q pointer,
The working program may look as this:
#include <stdio.h>
void change_it(int a[]);
int main()
{
int a[5] = {0}; // init all element of `a` to `0`
int *p; // declare int pointer
p = a; // p point to array `a`
// print the first element of array `a`
printf("a[0] has the value %d \n",(int)*p);
// call function change_it, pass `a` as the argument
change_it(a);
printf("a[0] has the value %d \n",(int)*p);
return 0;
}
// change the value of the first element of array `a` to 777
void change_it(int a[]) {
int i=777, *q; // declare int i and pointer
q = &i; // pointer `q` points to the `i` now
a[0] = *q; // a[0] is assigned value = 777;
}
Output:
a[0] has the value 0
a[0] has the value 777

how pointer assignment and increment is working in below example

I am learning the pointers in C. I am little confused about how below program is working
int main()
{
int x=30, *y, *z;
y=&x;
z=y;
*y++=*z++;
x++;
printf("x=%d, y=%p, z=%p\n", x, y, z);
return 0;
}
output is
x=31, y=0x7ffd6c3e1e70, z=0x7ffd6c3e1e70
y and z are pointing to the next integer address of variable x.
I am not able to understand how this line is working
*y++=*z++;
can someone please explain me how this one line is understood by C?
*y++=*z++; actually means
*y = *z;
y += 1*(sizeof(int)); //because int pointers are incremented by 4bytes each time
z += 1*(sizeof(int)); //because int pointers are incremented by 4bytes each time
So pointed value does not affected, pointers are incremented by one.

Change value in main using void sub-function

I am having trouble with this problem:
#include <stdio.h>
void change_number(int *x);
int main()
{
int x;
printf("Enter the number x: ")
scanf("%d", &x);
printf("In the main program: x = %d\n", x);
change_number(&x);
printf("In the main program: x = %d\n", x);
return 0;
}
void change_number(int *x)
{
x = *x+3;
printf("In the subroutine: x = %d\n", x);
}
Expected output:
Enter the number x: 555
In the main program: x = 555
In the subroutine: x = 558
In the main program: x = 558
Two notes:
I cannot modify main, or anything that comes before it. I can only modify the void change_number function, and the code inside it is my own code.
I cannot get the required output – my code only outputs x+3 in the subroutine, but doesn't change it in the main program.
How would I go about changing the value in the main routine? Please keep in mind that I am very new to C, and don't know many things yet (in fact, I just covered pointers yesterday).
The code
void change_number(int *x)
{
x = *x+3;
printf("In the subroutine: x = %d\n", x);
}
should read
void change_number(int *x)
{
*x = *x+3;
printf("In the subroutine: *x = %d\n", *x);
}
This will use the pointers as intended (you need to dereference them on the LHS as well)
I think an answer to the OP question needs a little bit explanation as C syntax may be confusing at times:
The function is declared as
void change_number(int *x)
The * means that the input parameter x is a pointer to a variable of type int. In other words x represents a location in memory.
Inside the function:
x is the address in memory of the int value
*x is the "content" of the memory address pointed by x
So, as other correctly pointed out, the function should be written as
void change_number(int *x)
{
*x = *x+3;
printf("In the subroutine: x = %d\n", *x);
}
Because as you act on *x you're acting on the content pointed by x
What is happening into main() ?
x is an int variable.
And you call:
change_number(&x);
The amplersand & means that you're not passing the value of x.
Instead you're passing a pointer to x, in other words the address in memory where the content of x is stored.
In other-other words x is passed by reference.
A final note: when writing a program in c (well, in any language, but expecially in c) the compiler warnings/errors and the debugger are your best friends.
Furthermore a good IDE will show you warnings as you type the code.
Anyway... the compiler should have warned you that
x = *x+3;
involves an implicit conversion from a int to int * (pointer to int) and most likely is a mistake.
You should use
*x = *x+3;
instead of
x = *x + 3;
What a function does with its parameters is, it makes a copy to work on and once the function's scope is ended, the copy is released which cannot change a value of a parameter passed to a function from outside.This is where pointers come in.
when passing a pointer to a function, think of it as a copy of the real address where in your case x is stored.
Thus in order to use x or change x, you have to use or change respectively *x(and it gets later dereferenced in the main program by &.
so like many others mentioned x = *x+3; should be *x = *x+3; and you'll get the desired results
Instead of printing in the change function you can also print in the main function by doing
*x=*x+3

Resources