0

I am learning c, and I am quite confused about this double pointer question.

int x = 44;
int *p = &x;
int **t = &p;

bool a = (*t = &x);

I need to tell whether a will be true or false, and the correct answer is true. My thoughts were that t points to the address of p, and p points to the address of x. I know if you put **t, it should point to the address of x, but I thought if you just put *t it should point to the address of p. Can anyone explain?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
prelude38
  • 107
  • 7

6 Answers6

2
int x = 44;

Declares integer variable x, which stores value of 44.

int *p = &x;

Declares integer pointer variable called p, p now stores the address of x.

int **t = &p;

Declares pointer to pointer of type int called t, t stores the address of p. (Pointers have addresses too)

bool a = (*t = &x);

In C;

'*' = Extracts the value from an address (Dereference)

'&' = Gives address of variable (Reference)

Since t is a pointer to the value stored in p. *t will be the value stored in p, which is the address of x. (We figured this out in the second line)

On the other hand since the & is used on variable x. This will extract the address of x.

Therefore *t == &x, which sets the boolean value a to true.

1

I know if you put **t, it should point to the address of x, but I thought if you just put *t it should point to the address of p.

Well, that is both right and wrong. The "point to the address of" should read "designate" and it is right.


First of all, you declared 3 variables

int x = 42;
int *p = &x;
int **t = &p;

Now this could be read as x is an int, *p is an int and **t is an int. Then we initialize x to value 42, then p to address of x, and t to address of p.

Given

int *p = &x;

the two L-value expressions x and *p not only are both of type int, and have the same value; they designate the same object. Just like 10565305 and Amy Finck designate the same user. This is also called aliasing - *p aliases x, just like Amy Fink and User 10565305 are your aliases on Stack Overflow (and the name x is not the object itself, just like you're a person, not a name).

Likewise with int **t = &p, we now notice that just like above, *t and p designate the same object, p. And ps current value is that of expression &x. Hence *t == &x must be true.

As for *ts type, if **t is an int, then *t must be int * (the law of conservation of stars in pointers ;) which of course matches the type of p, and type of &x.

0

It will be true. Here is the explanation:

In bool a = (*t = &x); the variable t holds address of p. You are de-referencing t i.e *t will point to the content stored in location of p.

The content stored in address of p is address of x. Remember *p = &x. Comparing *t == &x will then be true.

In the question you have mentioned *t = &x, if that is the original code it is still true, as assignment in (*t = &x); returns a non-null pointer. When that non-null pointer is converted to a boolean, it becomes true.

Shrikanth N
  • 652
  • 3
  • 17
  • 1
    The assignment in `bool a = (*t = &x);` returns a non-null pointer (not true). When that non-null pointer is converted to a boolean, it becomes `true`; only a null pointer would become `false`. The semantics end up being much the same, but the detailed steps are slightly different from "assignment will return 1 (true)". – Jonathan Leffler Oct 26 '18 at 22:44
  • Thanks for correcting me, will update my answer accrodingly. – Shrikanth N Oct 26 '18 at 23:04
  • My problem is in your third paragraph — since `p` is about to be assigned to via `*t`, the current value stored in `p` is largely immaterial (though it does happen to be `&x` before the assignment). Then you say "Comparing `*t == &x` will then be true". And I'm not sure whether you think that the assignment is equality, or you're hypothesizing a test before the `bool` line, or a test afterwards. As `&x` is assigned to `*t`, the value in `p` (aka `*t`) doesn't change; it is `&x` both before and afterwards. Your third paragraph says "you have mentioned `*t = &x`, which seems to understate it. – Jonathan Leffler Oct 26 '18 at 23:17
  • It's not precisely wrong, but I don't think you've made it clear. It might be better, perhaps, if you extended the code provided with `int y = 99;` and use `int *p = &y;` and you could then print various values and addresses before the `bool` line, and then explain what happens in the `bool` line, and print various values and addresses afterwards. I just find myself not sure whether I understand how you are explaining what's going on. And "yes", it is hard work making clear answers. I struggle with it all the time! – Jonathan Leffler Oct 26 '18 at 23:19
0

The first line declares a variable 'x' of type 'int', and assigns the numeric literal value 44 to that variable.

int x = 44;

The next line (2) declares a variable 'p' of type 'pointer to int', and assigns the value of the expression '&x' (which is the address of x, a pointer to int),

int *p = &x;

The next line (3) declares a variable 't' of type 'pointer to, pointer to int' (a pointer that contains a pointer to an int type), and assigns the expression '&p' (which is the address of p, a pointer to int,

int **t = &p;

The variable t is a 'doubly-indirected pointer'. Now comes the 'tricky part'.

The next line (4) declares a variable 'a' which is a bool(ean) variable (true/false), and assigns the value of the expression on the rhs (right hand side, '(*t = &x)'. The parenthesis are there to ensure the intended order of precedence is observed. So we evaluate the expression '*t = &x'.

bool a = (*t = &x);

Here is the 'tricky' part, the code provided has an assignment '=' operator! If this were comparison, then the '==' operator would appear. So this statement takes the address of x (pointer to int), and stores it into *t (the location pointed at by t, and that location is a pointer to int).

Were this comparison, the expression would compare the same values, and would be true. But this is assignment. And an assignment expression returns the value assigned, which is the address of x (pointer to x). On most systems, that pointer is a location in memory (and could only be zero(NULL) if the variable were stored at the zero address).

The expression is of type 'pointer to int', but is converted (cast) to type bool. Since C considers false=0 and true anything not equal to 0, the value is converted from (likely not NULL) pointer to int to bool (true).

Had the parenthesis been omitted, then the assignment would still occur (right to left order of evaluation for assignment operator), but then the cast would occur. But remove the parenthesis, compile it and see what your compiler says.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
ChuckCottrill
  • 4,360
  • 2
  • 24
  • 42
  • Note that no variable can ever have an address such that its address compares equal to the null pointer; C demands that. C11 [§6.3.2.3 Pointers ¶3](http://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p3): _An integer constant expression with the value 0, or such an expression cast to type `void *`, is called a null pointer constant.66) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function._ (Footnote 66 mentions that `NULL` is a macro that's defined as a null pointer constant). – Jonathan Leffler Oct 27 '18 at 00:04
  • @JonathanLeffler I thought some embedded systems used 0x00 for stuff, maybe bootloader code or something? I use old C 89 and dont work on embedded stuff much anymore, but how would one access 0x00 in memory with the NULL pointer comment you added? – Bwebb Oct 27 '18 at 00:09
  • 1
    Some microprocessors store the restart address in address 0, or thereabouts. But that's outside the scope of standard C — no standard C compiler is allowed to place a variable at an address that can be confused with the null pointer. See also the C FAQ and various other sources on the topic. Basically, you can't ever have `&x` generating a null pointer for any variable (object) `x`. So, "the value is converted from (the definitively not NULL) pointer to `int` to the `bool` value `true` or 1". And similarly for the previous paragraph. – Jonathan Leffler Oct 27 '18 at 00:13
  • If it were legitimate to access location 0 as an `int` (say), then you'd use `int *ip = 0; int val0 = *ip; *ip = 42;`. However, on most modern (non-embedded) systems, that's an almost guaranteed segmentation fault and core dump. If the restart address were at location zero, you might write: `void (*restart)(void) = 0; (*restart)(); // Or: restart();` to jump to location zero. But neither `&ip` nor `&restart` would return a null pointer. The exceptions to 'almost guaranteed segmentation fault' are so few that it is tempting to drop the 'almost'; there's almost never an exception to the rule. – Jonathan Leffler Oct 27 '18 at 00:17
  • _"The parenthesis are there to ensure the intended order of precedence is observed"_ Totally unnecessary in this case. – Lightness Races in Orbit Oct 27 '18 at 18:33
0

You said:

I need to tell whether a will be true or false, and the correct answer is true. My thoughts were that t points to the address of p, and p points to the address of x. I know if you put **t, it should point to the address of x, but I thought if you just put *t it should point to the address of p. Can anyone explain?

Here is my attempt an an explanation:

The bold part is where you are confused. **t == x == *p, and *t == &x == p.

**t references the value stored in at x's address, not the address itself.

*t =p references the address of x, and dereferencing either of them give you the value of x.

Does this explanation clear things up? I can expand or make a sample program if it helps.

sample scratch code would be to printf these values to gain clarity:

int x = 42;   //&x = 0x1234DEAD (or some other address, just picked one for an example)
int * p = &x; // p = 0x1234DEAD and &p = 0x5678BEEF  (agian an example address)
int **t = &p; // t = 0x5678BEEF

printf("%d and %d and %d\n",**t, *p, x); //should be 42;
printf("%p and %p\n",*t, p); //should be 0x1234DEAD;
printf("%p\n",t); //should be 0x5678BEEF;
Bwebb
  • 675
  • 4
  • 14
0

My thoughts were that t points to the address of p

Yes.

and p points to the address of x

Yes.

I know if you put **t, it should point to the address of x

No, **t is x.

but I thought if you just put *t it should point to the address of p.

No, *t is p.

The dereference operator "gives you" the pointed-to thing. Hence, since, p is also &x (because that's what you set it to), *t == &x.

It's moot though because you didn't actually compare with ==, you assigned with =, so your expression evaluates to the result of that assignment, which is &x, which is a non-NULL pointer, so the whole thing is "true-like". (Only a null pointer converts to false).

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055