#include <stdio.h>
void test(void **arg) {
int foo = 3;
**(int **)arg = foo; // I want to just fix this line!!
}
int main(void) {
int temp = 0;
printf("%d\n", temp);
test((void **)&temp);
printf("%d\n", temp);
return 0;
}
In my code, It has problem 'Segmentation fault', but I don't know how can I fix my code..
I wanna fix just **(int **)arg = foo; line.
Can Anybody Help Me?
In your code, function test(void **temp), variable temp is a pointer to a pointer, aka double pointer. That is to say, it value is an address. But when you call test from main, that value is 0, which means that address is address 0.
You can not assign a value to address 0.
It looks like you are writing to address 0.
Because:
&temp is a pointer to int.
*((int**)&temp) is an int.
**((int**)&temp) use your value from temp as address.
Your function
void test(void **arg);
expects a "pointer to pointer to void", that is the address of a location that contains another address pointing to a generic data.
When you call the function you are not passing what it expects
int temp = 0;
test((void **)&temp);
In fact &temp is an address pointing to an integer. But it expects the address of an address! So, when inside the function you deference it twice (every deferencing with the * operators means "resolving" one address) the second time you are trying to access the address 0.
In order to fix it, just pass to test a pointer to pointer:
int temp = 0;
int *tempAddr = &temp; //tempAddr points to temp
test((void **)&tempAddr); //The type of the address of tempAddr is 'int **'
You were actually asking a different thing: you explicitly asked for a fix of the **((int **) arg) = foo; line.
That's not so easy, as you are currently receiving an invalid pointer to pointer, and there's no way to make it valid just changing that line. In order to sort it out you would need to change test() interface, like shown below:
#include <stdio.h>
void test(void *arg) { // changed 'void **' to 'void *'
int foo = 3;
*(int *)arg = foo; // only one level of dereferencing
}
int main(void) {
int temp = 0;
printf("%d\n", temp);
test((void *)&temp); // cast to 'void *' instead of 'void **'
printf("%d\n", temp);
return 0;
}
Related
As I am a beginner in C
When I run the following C code :
#include<stdio.h>
void f(int *p)
{
*p=3;
}
int main()
{
int *p;
f(&p);
return 0;
}
I get these messages after compilation:
1) warning:passing arg 1 of 'f' from incompatible pointer type f(&p)
2) note: expected 'int *' but argument is of type 'int **' void
f(int *p)
Please note:
&p is the memory address of a variable
*p is the actual value of the variable
So what you are doing is:
In main: You are generating a variable pointer p. And you are passing this pointers address to a function f.
f thinks it gets a pointer as parameter but it gets a memory address and obviusly can't handle it.
More information is here
Hope I could help!
You're passing a pointer to a pointer as an argument to a function expecting a pointer to an int. They're two different types and the compiler will complain.
There is another issue where you have the 'pointer' to the int but not the space allocated to store it. There are a couple solutions to this situation.
1)
{
int q; // add a new int, to which p points to. this allocates memory for an int
int *p = &q;
f(p); // don't pass a pointer to a pointer, just the pointer
return 0;
}
2)
{
int p; // have p be the int in the first place, not a pointer
f(&p); // your original call is unchanged and works now
return 0;
}
It's hard to think about this, because there are multiple levels of pointers.
Here's a simpler example. This is what we might call "pass by reference":
#include <stdio.h>
void f(int *ip)
{
*ip = 5;
}
int main(){
{
int i = 7;
printf("%d\n", i);
f(&i);
printf("%d\n", i);
}
Function f accepts a pointer to an int. It modifies that int. In main, we have an int variable i. We take the address of that variable using &, and pass the resulting pointer to function f. In this way, function f is able to modify i in the caller. Note that function f takes a pointer to something, and that what it takes a pointer to is the type of i in the caller -- in other words, pointer to int.
Now let's look at another example. This time, instead of manipulating an int by reference, we're going to manipulate a pointer variable, a char *. (We're going to end up dealing with pointers to pointers.)
void g(char **sp)
{
*sp = malloc(10);
strcpy(*sp, "oranges");
}
int main(){
{
char *s = "apples";
printf("%s\n", s);
g(&s);
printf("%s\n", s);
}
Again, function g accepts an argument by reference. Again, function g is able to modify a variable in its caller. Again, the pointer type accepted by g is a pointer to the type being manipulated. Since the type being manipulated is "pointer to char", function g accepts a pointer to pointer to char, or char **.
But the code you posted is sort of a mixture of the two. Your function f accepts an int pointer, just like mine, and it tries to use that int pointer to modify an int variable in the caller. But then, in your main function, the variable you're trying to modify isn't an int, it's a pointer to int, or int *.
When you call
f(&p);
you're starting with a pointer-to-int, p, and you're taking its address with &, resulting in a pointer-to-pointer-to-int. But then you;re calling function f, which expects a pointer-to-int. That's what the compiler is trying to tell you with the messages
warning: passing arg 1 of 'f' from incompatible pointer type
note: expected 'int *' but argument is of type 'int **'
Why in this code the pointer shifts to another location:
#include <stdio.h>
void f(int *p)
{
int j=2;
p=&j;
printf("%d\n%p\n%d\n",*p,&j,p);
}
int main(void)
{
int *q;
int m=98;
q=&m;
f(q);
printf("%p ",q);
return 0;
}
Output:
2
0x7ffff5bf1bcc
0x7ffff5bf1bcc
0x7ffff5bf1bc8
I understand that when the function f() is done with printing value of j and address of j the memory occupied by j goes back to the stack but IMO p should continue pointing that location even after the function is over & it should be printing the same address in main as well. What is wrong with this?
Considering you meant printf("%p ", (void *)q); in the actual code,
No, function argument(s) in C is (are) passed by value. It won't reflect the changes made to the parameter into the actual arguments used (in function call) themselves.
To put it into other words, the function parameters are local to the function (call) scope, any changes made to them won't be reflected to the actual arguments.
So, if you need to change a pointer, you need to pass a pointer to the pointer which needs to be changed.
Consider a rather light-hearted but realistic scenario.
void f (int x) { x = 10; }
int main(void) { f(5); printf ("%d", 5); return 0;}
Now, do you expect it to print 10?
That said, an advice. Always cast the argument to %p conversion specifier to (void *) (if it is not already). printf() is a variadic function and for pointers, no default argument promotion happens, so the supplied argument type needs to match the expected type, explicitly. Otherwise, technically it is undefined behavior.
Learn the difference between Pointers and Pointers to pointers - the pointer passed p is no doubt good to change the value of the variable it is pointing to (m), but to change the memory location it is pointing to - you need a pointer to pointer.
Expanding on top of what #SouravGhosh said, when you pass in a pointer to an int you are making a copy of the pointer. If you wanted to change the pointer you need to be doubly indirect and pass in a pointer to a pointer to an int. The first pointer is copied and you can directly affect the second pointer.
void f(int ** p)
{
int j = 2;
*p = &j;
printf("%d\n%p\n%p\n",*p,&j,p);
}
int main(void)
{
int ** q = (int **)malloc( izeof(int *));
int m = 98;
*q = &m;
f(q);
printf("%p ",q);
free(q);
return 0;
}
And the output is
2
0xffffcbcc
0xffffcbcc
0xffffcbcc
If you do this you'll see that it never changes:
#include <iostream>
#include "Header2.h"
#include "header1.h"
#include <stdio.h>
void f(int *p)
{
int j = 2;
p = &j;
printf("%d\n%p\n%p\n", *p, &j, p);
}
int main(void)
{
int *q;
int m = 98;
q = &m;
printf("Value of pointer q before calling f() =%p ", q);
f(q);
printf("Value of pointer q after calling f() =%p ", q);
return 0;
}
I am trying to pass a variable into a function and change its global value but it does not work. Here is the simplified code:
int main()
{
int *Num = malloc (sizeof (int));
ChangeValue(&Num);
printf("Number is %i\n", Num);
}
int ChangeValue(int *temp)
{
*temp = 10
}
The error message is:
expected 'int *' but argument is of type 'int **'
I tried to change the function to int ChangeValue(int **temp) but received the following error:
warning: assignment makes pointer from integer without a cast.
Any suggestions?
int *Num means Num is of type int *. Since it's already an integer pointer, there's no need to take its address again when you pass it to your function that takes an int *.
ChangeValue(Num);
OTOH, since it is a pointer you will have to dereference it to use it as an integer, like with printf.
printf("Number is %i\n", *Num);
Variable Num is a pointer to an int (int*). Function ChangeValue(int*) takes a pointer to an int (int*). However, you are passing a pointer to Num (int**) to it.
Short answer: remove & before Num in ChangeValue(&Num);
Long answer: You seem to have a problem understanding how pointers work, you might want to read more about this before going further.
I have a function in C that needs to receive a pointer to an array (with an unspecified type).
To do so, I use void**, as I would use void* to receive an array of unspecified elements.
There's a problem unfortunately: the compiler gives a warning (passing argument 1 of 'f' from incompatible pointer type). If I ignore the warning, and try to execute the program, everything works as expected.
The only way to get rid of the warning is to cast whatever I try to pass to the function to void**.
Why does C behaves like that? And is there a better way to solve the warning?
PS: I need to compile using GCC with the flags -std=gnu89 -pedantic -Wall
Example
int f(void** param){ return 1; }
int main(){
int *arr = malloc(sizeof(int) * 20);
int i;
for(i=0; i < 20; i++) arr[i] = i;
f(&arr);
}
The pointer to anything type is void*, and the compiler will not complain about conversions to that type. But void** is not a pointer to anything, it's a pointer to an array of pointers to anything, which is quite different from a pointer to an array of pointers to integers, so the compiler complains.
So, to solve the warning, yes you would need to cast explicitly.
Although void * is the "generic pointer" in C, void ** isn't a "generic pointer to pointer". Instead, it's nothing more than the "specific pointer to void *, the generic pointer".
In your case, a int ** is converted implicitly to a void **, which is not generic. Since a void ** is not guaranteed to be able to hold all pointer variables (thus incompatible to a int **), the compiler raises a warning.
Here is the warning generated by clang:
main.c:7:7: warning: incompatible pointer types passing 'int **' to parameter of
type 'void **' [-Wincompatible-pointer-types]
f(&arr);
^~~~
main.c:1:14: note: passing argument to parameter 'param' here
int f(void** param){ return 1; }
To eliminate this warning, you can have int f(void* param);, and cast param to int ** inside the function. There will be no warning because a void * can be used to store any pointer (Quoted from N1570):
6.3.2.3 Pointers
1 A pointer to void may be converted to or from a pointer to any
object type. A pointer to any object type may be converted to a
pointer to void and back again; the result shall compare equal to the
original pointer.
It seems that you want to modify the address of the data (not the value) inside the function, you can't do that directly with a void * because you can't use arithmetic with void *, but you can pass the size of the first element and a chunk of bytes (char *), suppose you want to change the address of arr to arr + 1 (the second element of the array) inside the function:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void f(void *ptr, size_t size)
{
// char *p = *ptr; Wrong, you can't dereference a void * without a cast
char *p = *(char **)ptr; /* pointer to address of ptr */
memmove(p, p + size, size); /* assign the address of ptr + 1 to ptr */
}
int main(void)
{
int *arr = malloc(sizeof(int) * 20);
int i;
for (i = 0; i < 20; i++) arr[i] = i;
f(&arr, sizeof arr[0]);
printf("%d\n", arr[0]);
return 0;
}
Output:
1
I want to pass a pointer as a size element of an array
example:
void hello(int array1[how can i refer pointer "ptr" here][2])
{
// i want to access the array used in the main() here
printf("hi");
}
int main()
{
int c=5;
int *ptr=&c;
a[*ptr][2];
a[0][1]=0;
a[0][2]=4;
}
I apologize for not being clear with my question here , i want to access the array used in the main() function in my hello() function.
You will have to use the value pointed to by the pointer:
a[*ptr][2];
ptr is the address pointed to by the pointer not the value stored there. You use the dereference operator * to get the value.
Of course, ptr is not of type int, it's of type int * (integer pointer). An array subscript must be of type int.
Maybe what you want is a[*ptr][2].
You need to deference the pointer by using *ptr so
int c = 5;
int *ptr = &c;
a[*ptr][2];
otherwise you are not using the value of ptr you are using its address in memory which returns an error.
Use the dereference operator *:
a[*ptr][2];
The expression *ptr tells the compiler to use the value pointed to by ptr.
As for your updated question, that's not possible. But it's not needed either, as it's passed as a pointer anyway.
When declaring a function, this:
void foo(int a[5][5])
is the same as this:
void foo(int a[][2])
And also the same as this:
void foo(int (*a)[2])
It has pretty much been answered already, you can't call an adress in the array a[0x3950f2][2]
Always use the pointer* to get the position in the array a[*ptr][2] to get the expected value - in this case: a[*ptr][2] == a[5][2]. You may read this.
Edit to your updated question: You can't to this. You can use the pointer when you call the function or when using the variable in the function.
Your second edit:
void hello(int **array1)
{
// i want to access the array used in the main() here
printf ("hi");
a[0][0] = 24;
}
int main()
{
int c = 5;
int *ptr = &c;
int **a;
a[*ptr][2];
a[0][1] = 0;
a[0][2] = 4;
hello (a);
return 0;
}