I have this int **i or int ***i or int ****k
how to assign value and to do printf to/of i, j and k?
also if I have
struct abc { int *i; int **j; int ***k; };
then how to assign and print values to i, j, k if I have
struct abc *b = ...;
struct abc **c = ...;
struct abc ***d = ...;
I assume malloc will never be needed.
update
I tried like this
int *i=malloc(sizeof(int)*2);
i[0]=5;
int **j=(int **)i;
int ***k=(int ***)j;
printf("%d\n",k[0][0][0]);
but at printf it throws segFault
And also
int *a=malloc(sizeof(int)*3);
int *b=malloc(sizeof(int)*3);
int *c=malloc(sizeof (int) *3);
int **i={a,b,c};
i[0]=a;
i[1]=b;
i[2]=c;
i[0][0]=5;
printf("%d\n",i[0][0]);
again segFault at printf
Update
and how to call scanf and pass i, j and k, and abc like in chqrlie answer ?
and if I have a function like
void call_this(struct abc ***d)
{
//how to assign and print
}
Here is an example without any malloc() calls:
#include <stdio.h>
struct abc { int *i; int **j; int ***k; };
int main() {
int n;
int *p = &n;
int **pp = &p;
int ***ppp = &pp;
struct abc a = { p, pp, ppp };
struct abc *b = &a;
struct abc **c = &b;
struct abc ***d = &c;
n = 42;
// all expressions ulimately point to the same integer
printf(" n=%d\n", n);
printf(" *p=%d\n", *p);
printf(" **pp=%d\n", **pp);
printf(" ***ppp=%d\n", ***ppp);
printf(" *a.i=%d\n", *a.i);
printf(" *(*b).i=%d\n", *(*b).i); // same as *b->i
printf(" *(**c).i=%d\n", *(**c).i); // same as *(*c)->i
printf(" *(***d).i=%d\n", *(***d).i); // same as *(**d)->i
printf(" **a.j=%d\n", **a.j);
printf(" **(*b).j=%d\n", **(*b).j); // same as **b->j
printf(" **(**c).j=%d\n", **(**c).j); // same as **(*c)->j
printf(" **(***d).j=%d\n", **(***d).j); // same as **(**d)->j
printf(" ***a.k=%d\n", ***a.k);
printf(" ***(*b).k=%d\n", ***(*b).k); // same as ***b->k
printf(" ***(**c).k=%d\n", ***(**c).k); // same as ***(*c)->k
printf("***(***d).k=%d\n", ***(***d).k); // same as ***(**d)->k
return 0;
}
Output:
n=42
*p=42
**pp=42
***ppp=42
*a.i=42
*(*b).i=42
*(**c).i=42
*(***d).i=42
**a.j=42
**(*b).j=42
**(**c).j=42
**(***d).j=42
***a.k=42
***(*b).k=42
***(**c).k=42
***(***d).k=42
The parentheses in the above expressions are required because of precedence rules. Postfix unary operators are applied first from left to right, then prefix unary operators are applied from right to left. ***(***d).k is parsed as *(*(*(*(*(*d))).k)), which is even less readable.
Note however that it is considered bad style to use triple indirections, that are rarely needed in practice. Don't be a 3 star programmer
First we need to create object to assign addresses to that b, c and d variables
struct abc a; // create empty object
int tmp = 1; // create int to store it's address in a
a.i = &tmp; // store address of tmp in i
a.j = &a.i; // store address of i in j
a.k = &a.j; // store address of j in k
Then we can assign a's reference to b
struct abc *b = &a;
Then to c and d
struct abc **c = &b;
struct abc *** d = &c;
Now we have 1 object a and have direct address it via b, also we have direct address to b via c and so on...
We can also access a from c. First we need to get address of b
printf("%p", c); // address of b
printf("%p", *c); // address of a
struct abc a_cpy = **c; // create copy of object a
printf("%p", a_cpy.i); // address that was stored in the copy of a
Related
I wrote this simple function in C to swap the Value in 2 addresses in memory:
void pointersswap (int *ptr1, int *ptr2)
{
*ptr1 = *ptr1*(*ptr2);
*ptr2 = *ptr1/(*ptr2);
*ptr1 = *ptr1/(*ptr2);
}
I've been told there is an "edge case" that this program can encounter.
You can assume the input is correct (ptr1 and ptr2 actually hold address values and these addresses point to the memory where there's 2 ints which aren't 0). Math always checks out, even if either dereferenced pointer holds a negative number, or both are negative, or fractions.
For reference, this code Shouldn't have the same issue / edge case:
void pointersswap (int *ptr1, int *ptr2)
{
int temp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = temp;
}
What am I missing? are there really any limitations / edge cases in the first function?
Small clarification: assume there's not overflow / loss of information.
Firstly, "expressions" like *ptr1/*ptr2 won't work because /* is interpreted as the beginning of comments in C.
After replacing /* with / *, there are (at least) two cases in which the function won't work:
When the multiplication overflows.
When pointers to the same variable is passed to both a and b.
#include <stdio.h>
void pointersswap (int *ptr1, int *ptr2)
{
*ptr1 = *ptr1*(*ptr2);
*ptr2 = *ptr1/ *ptr2;
*ptr1 = *ptr1/ *ptr2;
}
int main(void) {
int a, b;
a = 999999; b = 888888;
printf("before: a = %d, b = %d\n", a, b);
pointersswap(&a, &b);
printf("after ; a = %d, b = %d\n", a, b);
a = 12345;
printf("before: a = %d\n", a);
pointersswap(&a, &a);
printf("after : a = %d\n", a);
return 0;
}
Output:
before: a = 999999, b = 888888
after ; a = 891245, b = -192
before: a = 12345
after : a = 1
I have been mislead, and so I mislead anyone who tried answering my question and for that I apologize. The two codes had the same edge case, which was that both pointers point to the same address, like MikeCAT suggested in his answer.
#include<stdio.h>
int g(int *a, int *b);
int main()
{
int a = 2;
int b = 7;
b = g(&b , &a);
printf("a = %d\n", a);
printf("b = %d\n", b);
return 0;
}
int g(int *a, int *b)
{
(*a) = (*a) + 3;
(*b) = 2*(*a) - (*b)+5;
printf("a = %d, b = %d\n", *a, *b);
return (*a)+(*b);
}
The output is:
a = 10, b = 23
a = 23
b = 33
I'm in an Intro to C programming class and having trouble understanding how this works.
Thanks for the help!
Sequencing the events as presented in question:
int main()
{
Declaration of a and b and value assignment:
int a = 2;
int b = 7;
Here is a trick, the address passed to the parameter int* a is actually of b, and vice-versa on the second parameter:
b = g(&b , &a);
Here just printing values of a and b:
printf("a = %d\n", a);
printf("b = %d\n", b);
return 0;
}
Since the parameters are pointers, the changes made, in the scope of this function, to the variable addresses pointed by them are permanent:
int g(int *a, int *b) {
Here, dereferencing the pointer (*a, the parentheses are not needed in these cases), means you are now working with the value stored in the address pointed by a, so 7 + 3 = 10, now the value stored in the address pointed by a is = 10:
(*a) = (*a) + 3;
Here, the same thing, dereferencing pointers, so 2 * 10 - 2 + 5 = 23, the value stored in the address pointed by b will be 23:
(*b) = 2*(*a) - (*b)+5;
Here printing a = 10 and b = 23, again, dereferencing pointers means you are working with the values stored in the addresses pointed by them:
printf("a = %d, b = %d\n", *a, *b);
The returned value is 10 + 23 = 33, so for b = g(&b, &a), b will be assigned the value of 33, a is already 23 so it stays that way:
return (*a)+(*b);
}
Remember that C passes all function arguments by value - that means that the formal parameter in the function body is a separate object in memory from the actual parameter in the function call, and the value of the actual parameter is copied to the formal parameter.
For any function to modify the value of a parameter, you must pass a pointer to that parameter:
void foo( T *ptr ) // for any type T
{
*ptr = new_T_value(); // write a new value to the thing ptr points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
In the code above, all of the following are true:
ptr == &var
*ptr == var
Thus, when you write a new value to the expression *ptr, it's the same as writing a new value to var.
I think part of what's making this confusing for you is that the names of your formal parameters (a and b) and your pointers (a and b) are flipped - g:a points to main:b and vice versa.
g:a == &main:b // I'm using g: and main: here strictly to disambiguate
*g:a == main:b // which a and b I'm talking about - this is not based on
// any real C syntax.
g:b == &main:a
*g:b == main:a
With & you give the address of the variable to the function, instead of the value.
With * you can access the value of an address.
With b = g(&b , &a); you give the address of the variable b and a to the function.
But you can access the address of b with * a because you declare the function that way: int g (int * a, int * b):
*a points to the address of your b variable.
*b points to the address of your a variable.
I think the different variable names are what confuses you.
To make it easier for yourself you could change the declaration to int g (int * b, int * a)
In case you want to change it:
*b would point to the address of your b variable and
*a would point to the address of your a variable.
by using the * you access the object referenced by the pointer. As the pointers are referencing int variables a & b you do the operations on those variables. I think the same variable names are confusing you
int g(int *p1, int *p2)
{
(*p1) = (*p1) + 3;
(*p2) = 2*(*p1) - (*p2)+5;
printf("*p1 = %d, *p2 = %d\n", *p1, *p2);
return (*p1)+(*p2);
}
#include<stdio.h>
void fun(int **a,int **b)
{
int **k;
k=a;
a=b;
b=k;
}
int main()
{
int a=3,b=6,*x=&a,*y=&b;
fun(&x,&y);
printf("%d %d",a,b);
return 0;
}
I swap the address,why it still outputs 3 6.
So what's the correct way to swap the two address?
p = ... never persists across the function call. Like everything else in C, if you want to change the caller's data, dereference the pointers you're given. k should be int *, and the assignments should be int *k = *a; *a = *b; *b = k;. that's it. Note also this changes nothing about the original a and b. All your swapping at this point are pointer values.
This code swaps two integers
#include<stdio.h>
void fun(int *a,int *b)
{
int k = *a;
*a = *b;
*b = k;
}
int main()
{
int a=3,b=6;
printf("%d %d\n",a,b);
fun(&a,&b);
printf("%d %d\n",a,b);
return 0;
}
Output
3 6
6 3
Whereas, this code swaps two pointers. The integers they point to (a and b) remain as-is.
#include<stdio.h>
void fun(int **a,int **b)
{
int *k = *a;
*a = *b;
*b = k;
}
int main()
{
int a=3,b=6,*x=&a,*y=&b;
printf("%d %d\n",a,b);
printf("%d %d\n",*x,*y); // note using x and y with deref
fun(&x,&y);
printf("%d %d\n",a,b);
printf("%d %d\n",*x,*y); // note using x and y with deref
return 0;
}
Output
3 6
3 6
3 6
6 3
Lets make it clear from the first expression .
int a=3,b=6,*x=&a,*y=&b;
Now breaking it down .
int a = 3, b = 6
Here a and b are two memory locations . Say a is 10000000 and b is 10010000. So , after we write a = 3 , b = 6 the value 3 takes the place in memory location 10000000 and 6 in 10010000 . Now ,
*x=&a,*y=&b;
means , x is an integer pointer that has the address of integer variable a which is 10000000 and y has the address of b which is 10010000 . Note that , both x and y are also variable which can store the address as value of any integer variable . x and y has locations in memory let say 11000000 and 11011111. Now ,
fun(&x,&y);
You are passing the address of x and y to the function fun . It looks like fun(11000000, 11010000) .
Note that , you are not passing the address of a and b ! In function fun these addresses are in a ( pa for clarity ) and b (pb for clarity),
void fun(int **a,int **b)
{
int **k;
k = a;
a = b;
b = k;
}
Here , a(pa), b(pb) and k are pointers of pointer . They can hold the address of an integer pointer .a(pa) and b(pb) are holding the address of x and y respectively . Now when you swapping a(pa) and b(pb) you actually swapping the addresses ( of x and y ) in a(pa) and b(pb). So , after the function fun finishes it's execution a (pa) is pointing y and b(pb) is pointing x . In main function , nothing actually happened . When you do the following ,
void fun(int **a, int **b)
{
int *k;
k=*a;
*a = *b;
*b = k;
}
it swaps the address in x and y and they now pointing to b and a(in main function).
Now the final version comes ! If you would do the following , it actually make you happy ,
void fun(int **a, int **b)
{
int k;
k=**a;
**a = **b;
**b = k;
}
I hope you understand it . Happy coding !
Try this to swap the values to which *a and *b of fun() points
void fun(int **a, int **b)
{
int k;
k = **a;
**a = **b;
**b = k;
}
Instead of this:
int **k;
k=a;
a=b;
b=k;
you should have tried this:
int *k;
k=*a;
*a=*b;
*b=k;
And yeah, you should print *x and *y, because those are the variables you swap, not a and b.
static void swapAddr(int *numOne, int *numTwo)
{
int *tmp;
tmp = numOne;
numOne = numTwo;
numTwo = tmp;
}
int main(void)
{
int a = 15;
int b = 10;
printf("a is: %d\n", a);
printf("Address of a: %p\n", &a);
printf("b is: %d\n", b);
printf("Address of b: %p\n", &b);
swapAddr(&a, &b);
printf("\n");
printf("a is: %d\n", a);
printf("Address of a: %p\n", &a);
printf("b is: %d\n", b);
printf("Address of b: %p\n", &b);
return 0;
}
When I compile and run this piece of code, the output is
a is: 15
Address of a: 0x7fff57f39b98
b is: 10
Address of b: 0x7fff57f39b94
a is: 15
Address of a: 0x7fff57f39b98
b is: 10
Address of b: 0x7fff57f39b94
Clearly the result is not what I intended, since the address does not seem to have been swapped at all.
You generally can't change the address of a variable.
Your 'swapAddr' function changes its parameter values, but these are local to the function - you're not changing anything outside the function. Perhaps the best way of understanding it is that a function parameter always receives a copy of the value that was passed to the function. In this case, you get a copy of the address of a and a copy of the address of b. You can and do change the values of the variables holding those copies (numOne and numTwo), and seeing as they are pointers you could (but don't) change the values that they point at (the values of variables a and b) - but you can't change the addresses of the original variables.
To break it down:
static void swapAddr(int *numOne, int *numTwo)
{
int *tmp;
tmp = numOne;
At this point, tmp and numOne both point to the value of the a variable...
numOne = numTwo;
Now, numOne points instead to the value of the b variable...
numTwo = tmp;
}
And finally, numTwo now points to the value of the a variable. The function returns and numOne and numTwo no longer exist after that point. The addresses of the variables a and b did not change at any stage.
You could however write a function which exchanges the addresses in two pointer variables:
static void swapAddr(int **ptrOne, int **ptrTwo)
{
int *tmp;
tmp = *ptrOne;
*ptrOne = *ptrTwo;
*ptrTwo = tmp;
}
This would allow you to pass the address of two pointer variables, and on return the pointers would be swapped - each one pointing at what the other did previously. But again, this would not change the address of any variable that those pointers happened to point to.
The pointers are passed to the function by value, so changing what they point to isn't going to change the value of the passed parameters in the calling function.
When the function is called, a copy of each pointer is made and saved to the stack. Then the function reads each pointer value off the stack and manipulates them. It never changes the value of the original pointer that was copied onto the stack.
Remember that in C values are passed by value to functions, meaning that the values are copied. When you modify an argument in a function you only modify the local copy inside the function, not the original value that was passed to the function. This goes for pointers as well.
To solve your problem you must pass the arguments by reference, but unfortunately C doesn't have that, it only have pass by value. However, pass by reference can be emulated by passing pointers to the data, just like you do in the function. You must however dereference the pointer to get the values from where the pointers point to, and use those values to do the actual swapping:
int temp = *numOne; // Note: temp is a value not a pointer
*numOne = *numTwo;
*numTwo = temp;
static void swapAddr(int *numOne, int *numTwo)
In this function you are passing 2 pointers by value. This allows you to modify the int pointed to by the pointers but not the pointers themselves.
Use this function definition instead that passes pointers to pointers and allows modifying the pointers themselves
static void swapAddr(int **numOne, int **numTwo) {
int *tmp = *numOne;
numOne = *numTwo;
numTwo = tmp;
}
You could use it like this for example:
int *a = malloc(sizeof(int));
int *b = malloc(sizeof(int));
*a = 15;
*b = 10;
swapAddr(&a, &b);
You canlt change the addresses. The adderss of a is the address of a and that will remain the same until the end of days.
You can do:
static void swapAddr(int **numOne, int **numTwo)
{
int *tmp;
tmp = *numOne;
*numOne = *numTwo;
*numTwo = tmp;
}
int main(void)
{
int a = 15;
int b = 10;
int *pa= &a;
int *pb= &b;
swapAddr(&pa, &pb);
}
What you want to achieve is something like
int *c = &a;
&a = &b;
&b = &a;
This is not possible (you can check: it will not compile). A variable that is created is placed at one place in memory and stays there. So when you create a variable a it will stay variable a and it will not be able to change its identity to that of another variable b.
What you can do is use two pointers int *p1, *p2 to int. These pointers can change their value and point to other objects during lifetime:
p1 = a;
p2 = b;
p1 = b;
p2 = a;
a and b will stay the same, but p1 and p2 can point to different objects over time.
So a thing that would be possible:
static void swapaddr(int **pp1, int **pp2)
{
int *pp;
pp = *pp1;
*pp1 = *pp2;
*pp2 = pp;
}
int main(void)
{
int a = 15, b = 10;
int *pA = &a, *pB = &b;
swapAddr(&pA, &pB);
}
In this example a and b would keep their identity and address, but pA and pB would change their value and pA would point to b and pB would point to pA.
You cannot change the addresses of the variables.however you can change values of pointers,which store addresses as their value,here is an example :
#include <stdio.h>
void swapAddr(int **numOne, int **numTwo)
{
int *tmp;
tmp = *numOne;
*numOne = *numTwo;
*numTwo = tmp;
}
int main(void)
{
int a = 15;
int b = 10;
int *p_a = &a;
int *p_b = &b;
printf("Address of a: %p\n", p_a);
printf("Address of b: %p\n", p_b);
swapAddr(&p_a,&p_b);
printf("\n");
printf("p_a : %p\n",p_a);
printf("p_b : %p\n",p_b);
return 0;
}
#include <stdio.h>
void swap (int *a, int *b)
{
int *tmp;
*tmp = *a;
*a = *b;
*b = *tmp;
}
int main ()
{
int x = 5;
int y = 7;
swap (&x,&y);
printf ("\n x = %d \n y = %d \n",x,y);
}
I'm using codeblocks, and this code won't work, and I don't understand why... On one computer it works perfectly but on the other it won't run at all.
Any help?
Thanks in advance.
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
What you need is a variable tmp to store the value and not a pointer *tmp.
The below code really a poor way of doing this but
int *tmp = malloc(sizeof(int));
*tmp = *a;
*a = *b;
*b = *tmp;
Once done please free the memory using
free(tmp);
Gopi already corrected your code - adding on to the previous answer - i think this is good to know information for a newbie:
Section 4.1 states:
An lvalue (3.10) of a
non-function, non-array type T can be
converted to an rvalue. If T is an
incomplete type, a program that
necessitates this conversion is
ill-formed. If the object to which the
lvalue refers is not an object of type
T and is not an object of a type
derived from T, or if the object is
uninitialized, a program that
necessitates this conversion has
undefined behavior. If T is a
non-class type, the type of the rvalue
is the cv-unqualified version of T.
Otherwise, the type of the rvalue is
T.
When you try to dereference and uninitialized pointer the behavior is undefined. Undefined means anything can happen - there is no guarantee. So you can get different behavior in different environments.
From Wiki Making pointers safer
A pointer which does not have any address assigned to it is called a wild pointer. Any attempt to use such uninitialized pointers can cause unexpected behavior, either because the initial value is not a valid address, or because using it may damage other parts of the program. The result is often a segmentation fault, storage violation or wild branch (if used as a function pointer or branch address).
What you did here:
int *tmp;
*tmp = *a;
is that you created a pointer to int which is not pointing to anything - basically it contains some junk value (could be your pincode even - who knows).
Your mistake was to use uninitialized memory. Always allocate memory to a pointer before using it. Next, don't forget to free the allocated memory after you're done with it.
Also, you should add return 0; at the end of your main() function.
If you don't mind a second opinion, check the below code.
#include <stdio.h>
#include <stdlib.h>
void swap (int *a, int *b)
{
int *tmp = malloc(sizeof(*tmp));
*tmp = *a;
*a = *b;
*b = *tmp;
free(tmp);
}
int main ()
{
int x = 5;
int y = 7;
swap (&x,&y);
printf ("\n x = %d \n y = %d \n",x,y);
return 0;
}
If you want to use pointers, although it does not make any sense at all
void swap(int *a, int *b)
{
int tmp[1];
*tmp = *a;
*a = *b;
*b = *tmp;
}
here tmp is not strictly a pointer, but you can use the * indirection operator on it.
Or
void swap(int *a, int *b)
{
int value = *a;
int *tmp = &value;
*tmp = *a;
*a = *b;
*b = *tmp;
}
Or you can use malloc as Gopi already pointed out.
If you want to use pointers, then do use pointers:
#include <stdio.h>
void swap (int ** ppx, int ** ppy)
{
int * p = *ppx;
*ppx = *ppy;
*ppy = p;
}
int main (void)
{
int x = 5;
int y = 7;
int * px = &x;
int * py = &y;
printf ("\nx = %d\ny = %d\n", *px, *py);
swap (&px, &py);
printf ("\nx = %d\ny = %d\n", *px, *py);
return 0;
}
Result:
x = 5
y = 7
x = 7
y = 5