Questions on compound literals in C - c

COMPOUND LITERALS:
#include<stdio.h>
struct s{
int x;
int y;
};
int main(){
int j = 5;
printf("\n &j : %p \n",&j);
struct s *p = &(struct s){j++};
printf("\n p : %p &j : %p x : %d y : %d \n",p,&j,p->x,p->y);
return 0;
}
o/p:
-----
&j : 0x7fff416b74ec
p : 0x7fff416b74d0 &j : 0x7fff416b74ec x : 5 y : 0
a] Why is p not holding the address of j ?
b] why is j not being typecast to struct s ?

a) p not holds the address of j because p point to freshly created structure.
if you want, that p point to j, you should write:
int * p = &j;
b) j is int local (stack) variable, so i see no way, how it can be cast into the structure.
#David C. Rankin, i've reformed my answer

The statement
struct s *p = &(struct s){j++}; // compiler should raise a warning
is incomplete. It should be like
struct s *p = &(struct s){.x = j++};
or
struct s *p = &(struct s){.y = j++};
The uninitialized member will be set ti 0 by default.
The reason that p doesn't hold the address of j is clear that p is holding the address of new object (compound literal), not the address of j itself.

for your first question,, p is of struct type and j is of integer type and you have to make the pointer and the variable of same datatype...
like int *p = &j; //where j is of int type.

j is of integer type(primitive data) and you are trying to convert it into complex datatype(object).. thus, you are trying to do boxing and unboxing.. which are not concepts of c or c++...

Related

how to handle dereference operator in the following cases

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

How to use a member of a structure defined by a compound literal?

I´ve found this piece of code, which uses a pointer to a structure made by a compound literal:
int main()
{
struct s {int i; int x;} *p;
int j = 0;
p = &((struct s){ j++ });
}
My questions are:
How is j++ a valid expression for modifying i and/or x and to what it get evaluated?
And how can I access the member i or x? Pointer offsets of p?
In a compound literal, any unspecified members get default-initialized, just like an initializer list for an object. So
(struct s){ j++ })
is equivalent to
(struct s){ j++, 0 })
j++ is the old value of j before j is incremented, just as in any other assignment. So this will set p->i = 0 and j = 1.
You can access the members using pointer dereferencing.
int x = p->x;
int i = p->i;

Why does the address of a pointer var change in this scenario?

So, I'm following "Let Us C" book, and they have an example for pointers, can you explain why the value of i and j change values in this scenario?:
main( )
{
int i = 3, *j, **k ;
j = &i ;
k = &j ;
printf ( "\nAddress of i = %u", *k ) ;
printf ( "\nAddress of j = %u", &j ) ;
}
Output
Address of i = 65524 Address of j = 65522
I understand in C that new variable declarations for example int i =3; int k=5 are assigned different memory locations by C, just cant seem to wrap my head around why this is outputting different values?
You are expecting *k (Same as address of i) and &j (address of j) to be same. They are different type int * v/s int ** and different values.
Never use %u to print addresses rather use:
printf ( "\nAddress of i = %p", (void *)*k ) ;
On the other hand, if you compare &j and k, those should be same.
For example:
printf ( "%p v/s %p\n", (void *)&j, (void *)k);
Because you are printing the pointer to k in the first printf statement, not the actual value of k. k holds the value of j's reference, so if you wanted the two statements to be equal, just print k.
Point 1: use %p to print the address. Also, cast the corresponding argument to (void *)
Point 2: *k (type int *) and &j (type int **) are two different things. Maybe you wanted to print either of
k and &j (both int **)
*k and j (both int *)
printf ( "\nAddress of i = %u", *k );
Here *k prints the value stored at j not the address of j.
To get the address of j, you need to print k without de-referencing it.
Assume that your variables are stored in following location.
Note: Addresses are just an assumption.
Now *k means de-reference the value stored at k (ie) value stored at memory location 200.
Value stored at 200 is 100 which is the address of i,not the address of j.
When your program start, the OS kernel decides, based on many criteria, where to put your program and how to map it into memory.
So, when you start it several time in a row, the memory location may or may not change.
This is why you can't hard-code absolute memory location in your program, you always pick a start point how know (for instance, the first element of an array) and navigate in your memory from here.
when your program starts, each variable gets a place in memory:
int i = 3, *j, **k ;
in your case, we know these adresses got decided:
address of (int i) = 65524
address of (int* j) = 65522
address of (int** k) = unknown
the operator & gets the adress of the variable, so you get the output you observe.
Given the code
int i = 3, *j, **k ;
j = &i ;
k = &j ;
then the following are true:
**k == *j == i == 3
*k == j == &i
k == &j
That is, the expressions **k, *j, and i all have type int and evaluate to 3, the expressions *k, j, and &i all have type int * and evaluate to the address of i, and the expressions k and &j have type int ** and evaluate to the address of j.
So,
printf( "value of i = %d\n", i );
printf( "value of i (through j) = %d\n", *j );
printf( "value of i (through k) = %d\n", **k );
printf( "address of i = %p\n", (void *) &i );
printf( "address of i (through j) = %p\n", (void *) j );
printf( "address of i (through k) = %p\n", (void *) *k );
printf( "address of j = %p\n", (void *) &j );
printf( "address of j (through k) = %p\n", k );
printf( "address of k = %p\n", (void *) &k );
Use the %p conversion specifier to print pointer values. It expects a void * as its corresponding argument, and this is one of the few places (probably the only place) in C where you need to explicitly cast a pointer value to void *.

Printing a variable in C that was not assigned a value

I put this code into eclipse and run it
main()
{
int *p, *q, *r;
int a = 10, b = 25;
int c[4] = {6,12,18,24};
p = c;
printf("p = %d\n" ,p);
}
the output I get is
p = 2358752
what is this number supposed to represent? Is it the address of the variable?
If what i'm saying above is true would my answer to the following question be correct?
so lets say the following are stored at the following locations
address variables
5000 p
5004 q
5008 r
500C a
5010 b
5014 c[0]
5018 c[1]
501C c[2]
5020 c[3]
so would would the line
p = c;
be 5014?
int *p,
The above statement defines p to be a pointer to an integer.
In the below statement, c is implicitly converted to a pointer to the first element of the array a.
p = c;
// equivalent to
p = &c[0];
Therefore, p contains the address of the first element of the array. Also, the conversion specifier to print an address is %p.
printf("p = %p\n", (void *)p);
// prints the same address
printf("c = %p\n", (void *)c);
Yes, p is the address of c, which is the same as the address of c[0]. And yes, in your second example, p would be equal to 5014.

Casting pointer & its address to integer pointer

What is the difference between the following two assignments?
int main()
{
int a=10;
int* p= &a;
int* q = (int*)p; <-------------------------
int* r = (int*)&p; <-------------------------
}
I am very much confused about the behavior of the two declarations.
When should i use one over the other?
int* q = (int*)p;
Is correct, albeit too verbose. int* q = p is sufficient. Both q and p are int pointers.
int* r = (int*)&p;
Is incorrect (logically, although it might compile), since &p is an int** but r is a int*. I can't think of a situation where you'd want this.
#include <stdio.h>
int main()
{
int a = 10; /* a has been initialized with value 10*/
int * p = &a; /* a address has been given to variable p which is a integer type pointer
* which means, p will be pointing to the value on address of a*/
int * q = p ; /*q is a pointer to an integer, q which is having the value contained by p, * q--> p --> &a; these will be *(pointer) to value of a which is 10;
int * r = (int*) &p;/* this is correct because r keeping address of p,
* which means p value will be pointer by r but if u want
* to reference a, its not so correct.
* int ** r = &p;
* r-->(&p)--->*(&p)-->**(&p)
*/
return 0;
}
int main()
{
int a=10;
int* p= &a;
int* q = p; /* q and p both point to a */
int* r = (int*)&p; /* this is not correct: */
int **r = &p; /* this is correct, r points to p, p points to a */
*r = 0; /* now r still points to p, but p points to NULL, a is still 10 */
}
Types matter.
The expression p has type int * (pointer to int), so the expression &p has type int ** (pointer to pointer to int). These are different, incompatible types; you cannot assign a value of type int ** to a variable of type int * without an explicit cast.
The proper thing to do would be to write
int *q = p;
int **r = &p;
You should never use an explicit cast in an assignment unless you know why you need to convert the value to a different type.

Resources