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.
Related
I don't understand where the error is in the function.I need to print 2 arrays with random elements.
int *boo3(int *x , int n){
x = (int*) malloc(sizeof(int)*n);
int i;
for(i=0;i<n;i++){
x[i] = rand()%10-(rand()%10);;
printf("%5d ",x[i]);
}
printf("\n");
}
int main(int argc, char *argv[])
{
int *x ,*y;
int n , m;
int i,j;
printf("enter size of X[n]: ");
scanf("%d",&n);
printf("enter size of Y[m]: ");
scanf("%d",&m);
x=boo3(*x,n);
y=boo3(*y,m);
free(x);
free(y);
return 0;
}
There are several problems with this code:
x = (int*) malloc(sizeof(int)*n); overwrites the function parameter x.
No return statement in boo3,
x=boo3(*x,m) in this line, *x is dereferencing pointer x which gives you int
In main function, you tried to free uninitialized pointer x and y
In your code
int *boo3(int *x , int n)
This indicates that you should receive a return value from this function.
In general a return value can be error code or any data which you might want to use going ahead.
Just like a math function for addition, taking operands as an argument and returning the sum. In your case, it is a pointer to the memory you have been allocated with.
In boo3() function, you are allocating some memory and you need the pointer to that memory for further usage. boo3() doesn't return anything, however, in main() function, you are assuming that you have caught it, hence the problem.
You should return the pointer to data from boo3().
I can see in main() function,
x=boo3(*x,n);
This is alarming. You are dereferencing a int* pointer and passing an int (instead of int*) as an argument to boo3() function which expects a int*.
If you wish to assign the pointer declared in main() with the address of memory allocated in boo3(), then you don't catch it and change to
boo3(x, n);
boo3(y, m);
And change to
void boo3(int *x , int n)
However, ideally, the function should return and the value be caught as a return value. In that case, change to
int* boo3(int n)
At the end of boo3 add a return x;. And use it as
x = boo3(n);
Additionally, you are not checking if the malloc() has allocated any memory or not. You should check if the pointer is NULL to see if memory is allocated. It is minimum error-checking and handling you need to have. Secondly, malloc() returns a void*, so the typecast is needless.
The problem is, you do not return anything from the function boo3(), and try to use the return value. This causes undefined behavior.
You need to add a return x; at the end of the function so as to return the pointer holding the address of the allocated memory (and populated values).
That said, passing the pointer argument is not needed when you return the pointer from the function. Apart from the fact that your call does not even try to pass a pointer as the first argument, as expected by the function signature - to allocate memory to a pointer from a called function, you need to pass the address of the pointer anyways, passing the pointer alone will not suffice. You don't need to do that, just define the function as
int *boo3(int n) { //......
and in the end, add
return x;
and from main(), call it like
x=boo3(n);
y=boo3(m);
There are many issues in your code.
Following has been corrected:
boo3 now simply returns the pointer to the allocated memory filled with random numbers, the useless x parameter has been removed and the function now contains the missing return statement. This is actually the main problem in your code.
The pointless (int*) cast has been removed from malloc.
The code is formatted properly.
Variables are declared as close as possible to their scope. This is the idiomatic way, declaring all variables at the start of the scope is a thing from the last century.
Usage of meaningful variable names.
This is a correct version of your program:
#include <stdlib.h>
#include <stdio.h>
int* boo3(int n) {
int *array = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
array[i] = rand() % 10 - (rand() % 10);;
printf("%5d ", array[i]);
}
printf("\n");
return array;
}
int main(int argc, char* argv[])
{
int sizex, sizey;
printf("enter size of X[n]: ");
scanf("%d", &sizex);
printf("enter size of Y[m]: ");
scanf("%d", &sizey);
int *xvalues = boo3(sizex);
int *yvalues = boo3(sizey);
free(xvalues);
free(yvalues);
return 0;
}
Disclaimer: for brevity there is no error checking for scanf and malloc.
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
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.
Pointers are a new thing for me and I'm struggling to understand it, but I won't give in and hopefully learn it.
What would be the difference between scanf ("%d", *p) and scanf ("%d", p)?
In examples I saw that if I want to input some value in a variable, I should use scanf ("%d", p). That doesn't make sense to me. Shouldn't it be scanf ("%d", *p)?
I interpret it as: "put some integer value where the pointer is pointing" and for instance it is pointing on variable x and then it should be x = 10, but it isn't. And how then to use scanf() and pointers to set values in an array?
Where and what am I getting wrong? I'm trying to learn this using C language, since it is the one which I'm supposed to use in my class.
For example:
#include <stdio.h>
int main () {
float x[10], *p;
int i;
p = &x[0];
for (i = 0; i < 10; i++) {
scanf("%d", p + i);
}
for (i = 0; i < 10; i++) {
printf("%d", *(p + i));
}
return 0;
}
Why is only p + i in the first for () {} and *(p + i) in the second loop? I would put *(p + i) also in the first for () {}. *(p + i) to me is like: "to what the (p+i)th element is and make it equal some value".
*p means go to the place p points to
&p means take the address of p, or "get a pointer to" p
int i;
scanf("%d", &i); // gives scanf a pointer to i
int i;
int *p = &i;
scanf("%d", p); // a more contrived way to say the same thing
The obligatory visual explanation is Pointer Fun with Binky.
You can read the types from right to left:
int *p => "p has type int *" => p is a pointer to an int
int *p => "*p has type int" => *p is the int pointed to by p
One is right, the other is wrong. (Or both may be wrong, depending on what p is.)
If you call
scanf("%d", SOMETHING);
then SOMETHING must be a pointer to an int.
If you have an int object, use unary & to get its address (i.e., a pointer to the object):
int n;
scanf("%d", &n);
If p happens to be an int*, then you can use its value:
int *p;
scanf("%d", p);
But here I haven't assigned a value to p, so this compiles but has undefined behavior. This is ok:
int n;
int *p = &n;
scanf("%d", p);
As for using *p, that would be valid only if p is a pointer to a pointer to an int:
int n;
int *p0 = &n;
int **p = &p0;
scanf("%d", *p);
But it would rarely make sense to do that. The vast majority of the time, the argument is going to be simply the address of some int object, like &n.
If n is an int, then just passing n to scanf wouldn't make sense. You'd merely be passing the current value of n. The point is that you want to permit scanf to store a new value in n, and to do that, scanf need's the address of n.
Function calls in C pass arguments by value, not by reference. This means that when you call a function with arguments, the function receives copies of the arguments, and that function cannot directly modify the original arguments from the callsite. That is:
int x = 42;
foo(x);
printf("%d\n", x);
foo cannot change the variable x, and the code will always print 42.
But there are many cases where a function might want to modify the arguments from the caller. scanf is one such case. To accomplish this, these functions require using a level of indirection. Instead of passing the variable to be modified directly to the function, the caller instead passes a pointer to that variable. The function then receives a copy of the pointer, and by dereferencing it, can access and can modify the variable it's pointing to.
I recommend spending some time reading the comp.lang.c FAQ. This topic is discussed in:
12.12a Why doesn't the call scanf("%d", i) work?
12.12b Why does the call scanf("%s", s) work?
If p is the variable (say, an int), you would use &p to pass its pointer to scanf. p alone is not a pointer, and *p compounds the problem.
I am a beginner. I was working around with pointer when I found something strange:
#include<stdio.h>
int* fun(int*);
int main()
{
int i=4,*j;
j=fun(&i);
printf("%d ",*j);//gives correct answer -> how??
printf("%d",*j);//gives incorrect answer
}
int* fun(int *i)
{
int k;
k=*i;
return (&k);
}
In main(), I am usingprintf("%d ",*j);` 2 times. First one is giving me right answer, but second one is not. Why?
but this is working fine-
#include
int *func();
int main()
{
int *p;
p=func();
printf("%u", p);
printf("\n%d", *p);
printf("\n%d", *p);
printf("\n%d", *p);
printf("\n%d", *p);
}
int* func()
{
int i=10;
printf("%u", &i);
printf("\n%d", i);
return (&i);
}
You are invoking undefined behavior by returning a pointer to a local variable. After the function fun returns, the space occupied by the local variable k is not valid anymore. Actually the space on the stack previously used by fun is probably overwritten by the first call to printf.
You're returning the address of a variable that's local to fun; once fun exits, that variable no longer exists, and the pointer is no longer valid. Strictly speaking, the behavior is undefined.
What's most likely happening is that the memory location that k used to occupy gets overwritten after the first call to printf.