Related
I created a function to return the pointer as follows:
int* function(int cc){
int* p;
p=&cc;
return p;
}
int main(){
int a;
int *p1;
a=10;
p1=&a;
printf("value for *p1 = %d\r\n",*p1);
printf("value for *function %d\r\n", *function(a));
printf("pointer p1 = %p\r\n", p1);
printf("pointer function= %p\r\n", function(a));
return 0;
}
The console log is shown as follows:
value for *p1 = 10
value for *function 10
pointer p1 = 0x16d4bb1f8
pointer function= 0x16d4bb1dc
I really don't understand why two pointers could show the same value, but the address they stored are different.
The variable you have passed in the function is done as a parameter (normal variable and not a pointer). If you really want the it should work like you expect then you should pass pointer instead of a normal int local variable.
Make these changes:
int* function(int *cc){
int* p;
p=cc;
return p;
}
int main(){
int a;
int *p1;
a=10;
p1=&a;
printf("value for *p1 = %d\r\n",*p1);
printf("value for *function %d\r\n", *function(&a));
printf("pointer p1 = %p\r\n", p1);
printf("pointer function= %p\r\n", function(&a));
return 0;
}
This code works and shows the output that you expect... We did this as we don't want a new copy of the variable passed into the function. We want the same address and so we should pass variable address in the function.
do this
void function(int cc){
int* p;
p=&cc;
cc = 42; // just for fun
printf("value of cc inside function %d\r\n", cc);
printf("value of &cc %p\r\n", &cc);
}
int main(){
int a;
int *p1;
a=10;
p1=&a;
function(a);
printf("value for *p1 = %d\r\n",*p1);
printf("pointer p1 = %p\r\n", p1);
return 0;
}
you will see that cc is a copy of a, if you change its value inside 'function' it does not change 'a'. You have found c's 'call by value' semantics. Meaning that variables are passed as copies to functions.
So basically I'd like to sum two numbers and return their value while using a void function in C. I know this is easy peasy by using a normal function returning an int or a numeric type but I wanna work on my pointer knowledge.
I tried creating a pointer inside main() and then passing it as an argument to the void function. Then I calculated my sum in a new int variable and assigned the pointer to point to that specific variable. The problem is I can't "retrieve" it or "find" that area of memory in the main function.
Here's what I've tried:
void testFunction(int a,int b, int *x)
{
int c=a+b;
x=&c;
}
int main()
{
int n1=7;
int n2=90;
int *pointerParam;
testFunction(n1, n2, pointerParam);
printf("Value of pointer is %d\n", *pointerParam);
}
It just exits with an error code, it does nothing. If I try to printf *x inside the function, it does work so I know that part at least works.
Any help would be greatly appreciated!
There are multiple problems with the code as it is shown.
The main problem is probably that you misunderstand how emulation of pass-by-reference works in C.
For it to work you need to pass a pointer to the variable that should be set. This is done using the pointer-to operator &. You also need to dereference the pointer, to set the variable the pointer is pointing to.
Putting it together your program should look something like this (simplified):
void testFunction(int a,int b, int *x)
{
// Assign to where `x` is pointing
*x = a + b;
}
int main(void)
{
int n1 = 7;
int n2 = 90;
int result; // Where the result should be written
// Pass a pointer to the `result` variable, so the function can write to it
testFunction(n1, n2, &result);
}
I will show you a program that is no more than a set of printf() and your function. Maybe the program's output helps in showing these pointers, arrays and integers things.
The example
Consider these variables
int n[4] = {10, 20, -30, -40};
int v1 = 0;
int v2 = 0;
int* a_pointer = NULL;
int* is a pointer to an int, that's the meaning of the asterisk in the declaration. In this context the asterisk is called the dereference operator or the indirection operator. But the asterisk also is the multiplication operator in C. ;)
Now a_pointer points to nothing, the meaning of the NULL.
But a_pointer is there to hold an address of something, of an int. The way of getting such address of something is the address of operator, the &, that also has an alternate life as the bitwise and operator in C. Things of life.
In printf() the %p specifier shows an address. This
printf("\naddress of v1 is %p\n", &v1);
printf("address of v2 is %p\n", &v2);
printf("address of array n[0] is %p\n", n);
printf("address of array n[0] is %p\n", 1 + n);
printf("address of array n[0] is %p\n", 2 + n);
printf("address of array n[0] is %p\n\n", 3 + n);
shows (in a 32-bits compilation)
address of v1 is 008FFDA0
address of v2 is 008FFD9C
address of array n[0] is 008FFDA4
address of array n[1] is 008FFDA8
address of array n[2] is 008FFDAC
address of array n[3] is 008FFDB0
And you will see the reason the program prints these lines in the code below...
This line
a_pointer = &v1;
takes the address of v1 and assign it to the pointer a_pointer.
Now a_pointer is pointing to something, to v1, and you can use it in your function. These lines are equivalent
testFunction(n[0], n[3], &v1);
and
testFunction(n[0], n[3], a_pointer);
In these lines
testFunction(n[0], n[3], &v1);
printf("n[0] = %d, n[3] = %d, sum in v1 is %d\n", n[0], n[3], v1);
printf(
"p points to v1. value is %4d, address is %p\n\n", *a_pointer,
a_pointer);
you see the use of the pointer to access the value it points to, using the dereference operator in the printf().
Follow the program along to see a few uses of this.
In particular, see these lines
a_pointer = n + 3;
printf(
"\np points now to n[3]. value is %4d, address is %p\n",
*a_pointer, a_pointer);
to see the thing C is made for: address memory easily. n is int[4], an array of int. a_pointer is a pointer to int. And the language knows that when you write a_pointer = n + 3 that it needs to add to the address of n, an int[], the size of 3 int variables, and assign it to the pointer, so *a_pointer is n[3]and it is used to call testFunction() in
testFunction(n[1], n[2], n + 3);
program output
n[] is [10,20,-30,-40], v1 is 0 v2 is 0
address of v1 is 00CFFA9C
address of v2 is 00CFFA98
address of array n[0] is 00CFFAA0
address of array n[1] is 00CFFAA4
address of array n[2] is 00CFFAA8
address of array n[3] is 00CFFAAC
n[0] = 10, n[3] = -40, sum in v1 is -30
p points to v1. value is -30, address is 00CFFA9C
p now points to v2. value is 0, address is 00CFFA98
n[0] = 10, n[1] = 20, sum in v2 is 30
n[] is [10,20,-30,-40], v1 is -30 v2 is 30
p now points to v1. value is -30, address is 00CFFA9C
n[] is [10,20,-30,-40], v1 is -30 v2 is 30
now makes n[3] = n[1] + n[2] using testFunction()
n[] is [10,20,-30,-10], v1 is -30 v2 is 30
p points now to n[3]. value is -10, address is 00CFFAAC
the code
#include <stdio.h>
show(int[4], int, int);
void testFunction(int, int, int*);
int main(void)
{
int n[4] = {10, 20, -30, -40};
int v1 = 0;
int v2 = 0;
int* a_pointer = NULL;
show(n, v1, v2);
printf("\naddress of v1 is %p\n", &v1);
printf("address of v2 is %p\n", &v2);
printf("address of array n[0] is %p\n", n);
printf("address of array n[1] is %p\n", 1 + n);
printf("address of array n[2] is %p\n", 2 + n);
printf("address of array n[3] is %p\n\n", 3 + n);
a_pointer = &v1;
testFunction(n[0], n[3], &v1);
printf("n[0] = %d, n[3] = %d, sum in v1 is %d\n", n[0], n[3], v1);
printf(
"p points to v1. value is %4d, address is %p\n\n", *a_pointer,
a_pointer);
a_pointer = &v2;
printf(
"p now points to v2. value is %4d, address is %p\n", *a_pointer,
a_pointer);
testFunction(n[0], n[1], &v2);
printf("n[0] = %d, n[1] = %d, sum in v2 is %d\n", n[0], n[1], v2);
show(n, v1, v2);
a_pointer = &v1;
printf(
"\np now points to v1. value is %4d, address is %p\n", *a_pointer,
a_pointer);
show(n, v1, v2);
printf("\nnow makes n[3] = n[1] + n[2] using testFunction()\n");
testFunction(n[1], n[2], n + 3);
show(n, v1, v2);
a_pointer = n + 3;
printf(
"\np points now to n[3]. value is %4d, address is %p\n",
*a_pointer, a_pointer);
return 0;
};
show(int n[4], int v1, int v2)
{
printf(
"n[] is [%d,%d,%d,%d], v1 is %d v2 is %d\n", n[0], n[1], n[2],
n[3], v1, v2);
};
void testFunction(int a, int b, int* sum)
{
*sum = a + b;
return;
}
I will not go into religious discussions here, but you may find easier to understand the meaning of the declarions if you write
int* some_int = NULL;
instead of
int *some_int = NULL;
you declare a name, and the name is some_int. The compiler will tell you that some_int is int*, its type. The fact that *some_int is an int is a consequence of the application of an operator to a variable.
You lacked just to understand how pointers are managed, but you were almost correct:
/* this is almost correct, you could have just said: *x = a + b; */
void testFunction(int a,int b, int *x)
{
int c=a+b;
*x=c; /* the pointed to value is what we are assigning */
}
int main()
{
int n1=7;
int n2=90;
int result; /* vvvvvvv this is the important point */
testFunction(n1, n2, &result); /* you pass the address of result as the required pointer */
printf("Value of pointer is %d\n", result);
}
Suppose I have a pointer
int *x;
Then I need to let the pointer point to an int of value, say 42.
Should I do this:
*x = 42;
or this:
int y = 42;
x = &y;
? What is the usual practice?
After this declaration
int *x;
the pointer x either is equal to NULL (if it is declared outside any function) or has an indeterminate value. So dereferencing the pointer like
*x = 42;
invokes undefined behavior.
You can write either
int y = 42;
x = &y;
or
x = malloc( sizeof( int ) );
*x = 42;
When you do:
int *x = 42;
you assigne the pointeur x to the memory case 42, that gonna make a segmentation fault.
The right way to do what you wan't is:
int y = 42;
x = &y;
x gets the adress of y (&y)
#include <stdio.h>
int main()
{
int y=42;
int x=&y;
printf("\nY = %d is at adress X = %d \n",y,x);
}
I am a Java programmer and recently play with C for fun. Now I am learning address and pointers which are a little bit confusing for me. Here is my question. See the below two blocks of the code.
void withinArray(int * a, int size, int * ptr) {
int x;
printf("ptr is %d\n", ptr);
printf("a is %d\n", a);
printf("difference in pointers is: %d\n", ptr - a);
x = ptr - intArray;
printf("x is %d\n", x);
}
void doubleSize() {
double doubArray[10];
double * doubPtr1;
double * doubPtr2;
doubPtr1 = doubArray;
doubPtr2= doubArray+1;
int p2 = doubPtr2;
int p1 = doubPtr1;
printf("p2-p1 is %d\n", p2-p1);
printf("doubPtr2-doubPtr1 is %d\n", doubPtr2-doubPtr1);
}
int main(void)
{
int a[10];
int *intarray = a;
int *p = intarray + 9;
printf(withinArray(a, 10, p));
return 0;
}
I am wondering for function withinArray(), why we could directly get the x value, which is 9? But for the other method, we have to convert doubPtr to int first and then we can get the difference between pointers in int?
From my understanding, in doubleSize(), doubPtr2-doubPtr1 = 1 means the difference in pointer address in memory is 1. But why the withinArray() doesn't need to do so?
A difference of 1 between two pointers means that the pointers point to adjacent units of memory of the size of the objects pointed at.
Thus, given:
int i[2];
int *ip0 = &i[0];
int *ip1 = &i[1];
double d[2];
double *dp0 = &d[0];
double *dp1 = &d[1];
we could safely write:
assert((ip1 - ip0) == (dp1 - dp0));
assert(ip1 - ip0 == 1);
assert(dp1 - dp0 == 1);
However, you could also safely write:
assert((char *)ip1 - (char *)ip0 == sizeof(int));
assert((char *)dp1 - (char *)dp0 == sizeof(double));
and usually you would find that it is safe to write:
assert(sizeof(double) != sizeof(int));
though that is not guaranteed by the standard.
Also, as Filipe Gonçalves correctly points out in his comment, the difference between two pointers is formally only defined if the pointers are of the same type and point to two elements of the same array, or point to one element beyond the end of the array. Note that standard C demands that given:
int a[100];
it is safe to generate the address int *ip = &array[100];, even though it is not safe to either read from or write to the location pointed at by ip. The value stored in ip can be used in comparisons.
You also formally cannot subtract two void * values because there is no size for the type void (which is why my example used casts to char *, not void *). Beware: GCC will not object to the subtraction of two void * values unless you include -pedantic in the options.
Do you know why the value of doubPtr2 - doubPtr1 (in my second method) is different from x = ptr - a (in my first method)?
Assuming that intArray is meant to be a, then this code:
#include <stdio.h>
static void withinArray(int *a, int *ptr)
{
int x;
printf("ptr is %p\n", (void *)ptr);
printf("a is %p\n", (void *)a);
printf("difference in pointers is: %td\n", ptr - a);
x = ptr - a;
printf("x is %d\n", x);
}
static void doubleSize(void)
{
double doubArray[10];
double *doubPtr1 = doubArray;
double *doubPtr2 = doubArray+1;
int p2 = doubPtr2;
int p1 = doubPtr1;
printf("p1 = 0x%.8X\n", p1);
printf("p2 = 0x%.8X\n", p2);
printf("p2-p1 is %d\n", p2-p1);
printf("doubPtr1 = %p\n", (void *)doubPtr1);
printf("doubPtr1 = %p\n", (void *)doubPtr2);
printf("doubPtr2-doubPtr1 is %td\n", doubPtr2-doubPtr1);
}
int main(void)
{
int a[10];
int *intarray = a;
int *p = intarray + 9;
withinArray(a, p);
doubleSize();
return 0;
}
compiles with warnings that I would ordinarily fix (change the type of p1 and p2 to uintptr_t, include <inttypes.h>, and format using "p1 = 0x%.8" PRIXPTR "\n" as the format string), and it generates the output:
ptr is 0x7fff5c5684a4
a is 0x7fff5c568480
difference in pointers is: 9
x is 9
p1 = 0x5C5684B0
p2 = 0x5C5684B8
p2-p1 is 8
doubPtr1 = 0x7fff5c5684b0
doubPtr1 = 0x7fff5c5684b8
doubPtr2-doubPtr1 is 1
Fixed code generates:
ptr is 0x7fff5594f4a4
a is 0x7fff5594f480
difference in pointers is: 9
x is 9
p1 = 0x7FFF5594F4B0
p2 = 0x7FFF5594F4B8
p2-p1 is 8
doubPtr1 = 0x7fff5594f4b0
doubPtr1 = 0x7fff5594f4b8
doubPtr2-doubPtr1 is 1
(The difference is in the number of hex digits printed for p1 and p2.)
I assume that your puzzlement is about why the int code prints 9 rather than, say, 36, whereas the double code prints 8 instead of 1.
The answer is that when you subtract two pointers, the result is given in units of the size of the objects pointed at (which I seem to remember saying in my opening sentence).
When you execute doubPtr2-doubPtr1, the distance returned is in units of the number of double values between the two addresses.
However, the conversion to integer loses the type information, so you effectively have the char * (or void *) addresses of the two pointers in the integer, and the byte addresses are indeed 8 apart.
If we make two symmetrical routines, the information is clearer:
#include <stdio.h>
#include <inttypes.h>
static void intSize(void)
{
int intArray[10];
int *intPtr1 = intArray;
int *intPtr2 = intArray+1;
uintptr_t p2 = (uintptr_t)intPtr2;
uintptr_t p1 = (uintptr_t)intPtr1;
printf("p1 = 0x%.8" PRIXPTR "\n", p1);
printf("p2 = 0x%.8" PRIXPTR "\n", p2);
printf("p2-p1 is %" PRIdPTR "\n", p2-p1);
printf("intPtr1 = %p\n", (void *)intPtr1);
printf("intPtr1 = %p\n", (void *)intPtr2);
printf("intPtr2-intPtr1 is %td\n", intPtr2-intPtr1);
}
static void doubleSize(void)
{
double doubArray[10];
double *doubPtr1 = doubArray;
double *doubPtr2 = doubArray+1;
uintptr_t p2 = (uintptr_t)doubPtr2;
uintptr_t p1 = (uintptr_t)doubPtr1;
printf("p1 = 0x%.8" PRIXPTR "\n", p1);
printf("p2 = 0x%.8" PRIXPTR "\n", p2);
printf("p2-p1 is %" PRIdPTR "\n", p2-p1);
printf("doubPtr1 = %p\n", (void *)doubPtr1);
printf("doubPtr1 = %p\n", (void *)doubPtr2);
printf("doubPtr2-doubPtr1 is %td\n", doubPtr2-doubPtr1);
}
int main(void)
{
doubleSize();
intSize();
return 0;
}
Output:
p1 = 0x7FFF5C93D4B0
p2 = 0x7FFF5C93D4B8
p2-p1 is 8
doubPtr1 = 0x7fff5c93d4b0
doubPtr1 = 0x7fff5c93d4b8
doubPtr2-doubPtr1 is 1
p1 = 0x7FFF5C93D4B0
p2 = 0x7FFF5C93D4B4
p2-p1 is 4
intPtr1 = 0x7fff5c93d4b0
intPtr1 = 0x7fff5c93d4b4
intPtr2-intPtr1 is 1
Remember Polya's advice in How to Solve It:
Try to treat symmetrically what is symmetrical and do not destroy wantonly any natural symmetry.
Complete C newb here. Trying to learn/understand pointers by messing with simple code fragments.
#include <stdio.h>
void swap(int *px, int *py)
{
int tmp;
tmp = *px;
*px = *py;
*py = tmp;
}
main()
{
int *a, *b;
*a = 1;
*b = 2;
swap(&a,&b);
printf("%d %d\n", *a, *b);
}
Why is this not valid? The code works when I remove the dereferencing operator * from main.
Conceptually, this seems like it should work. I initialize a and b as pointers which point to int 1 and int 2, respectively. I then send their addresses to swap(), which should switch what they point to.
There are a couple of problems. First, the pointers a and b are not pointing to valid memory. So the assignment of the integer values is undefined (possible crash). Secondly, the call to swap (assuming a and b are pointing to valid memory) should not include the address (it is currently sending the address of the pointer variable).
The following changes would make it work:
int a, b;
a = 1;
b = 2;
swap(&a,&b);
printf("%d %d\n", a, b);
The swap() function is OK but inside main you are taking the addresses of pointers, so you're passing int** arguments to int* parameters.
int *a, *b;
swap(&a,&b);
To fix it, replace the code in main() with :
int a = 1, b = 2;
swap(&a,&b);
printf("%d %d\n", a, b);
Pointers point to data. A pointer itself doesn't comprise memory for storage, it just points to existing memory. So when you declare int *a; , you just have a garbage pointer with no useable value, and you mustn't dereference it.
The only sensible way to use pointers is to assign them the address-of something (or the result of some allocation function):
int i;
int *a = &i; // now a points to i
Therefore, the right way to use your swap function is to pass it addresses of integers:
int i = 10;
int j = -2;
swap(&i, &j);
a and b are uninitialized pointers, dereferencing them induces undefined behavior. You want:
int main() {
int a, b;
a = 1;
b = 2;
swap(&a,&b);
printf("%d %d\n", a, b);
return 0;
}
Your method signature is wrong. You ask for two pointers to int, yet you pass in two pointers to pointers to int.
When you say, " I then send their addresses to swap(), which should switch what they point to." Are you trying to change the address values within the pointer variables in main, to switch which bit of memory they are pointing to? In that case you will need another step of redirection:
#include <stdio.h>
void swap(int **px, int **py) {
int *tmp;
tmp = *px;
*px = *py;
*py = tmp;
}
int main (void) {
int x, y; /* storage to point to */
int *a, *b;
a = &x;
b = &y;
*a = 1;
*b = 2;
printf("(*a, *b, x, y) == (%d, %d, %d, %d)\n", *a, *b, x, y);
swap(&a, &b);
printf("(*a, *b, x, y) == (%d, %d, %d, %d)\n", *a, *b, x, y);
}
$ ./a.out
(*a, *b, x, y) == (1, 2, 1, 2)
(*a, *b, x, y) == (2, 1, 1, 2)
The x & y values have not changed, but a was pointing to x and now points to y and vice versa for b.