Might be a silly question for you, and I couldn't find a good question for that, but the thing is - I don't understand and I'm asking you to explain that concept to me so I can understand, I would be really grateful.
So, the thing is - I was wondering, first of all, why that line of code:
printf("address of wsklan[0] %p\n", &wsklan[0])
would print different address than:
printf("address of wsklan[0][0] %p\n", &wsklan[0][0]);
I'm guessing that's because in the first case, that is an address of a pointer, and in the second one - an address of a char variable. But why exactly the address is different? I thought that the address of wsklan[0] is the address of the first char.
How is the string stored in memory? Is the string one after another in memory? So if I type 'onetwo' and second string 'threefour', it would be one after another?
And second question - why can't I use the puts function like this?:
puts(wsklan 1)
but I can use it like this?
puts(wsklan[1])
Full code snippet:
#include <stdio.h>
#include <string.h>
char *read(char *z, int amount);
int main(void){
char data[20][300];
char * wsklan[20];
read(data[0], 300);
read(data[1], 300);
wsklan[0] = data[0];
wsklan[1] = data[1];
printf("addres wsklan[0][0] %p\n", &wsklan[0][0]);
printf("addres wsklan[1][0] %p\n", &wsklan[1][0]);
puts(wsklan[0]);
puts(wsklan[1]);
putchar(*wsklan[1]);
return 0;
}
char *read(char *z, int amount){
char * res;
int i = 0;
res = fgets(z, amount, stdin);
if(res){
while(z[i] != '\n' && z[i] != '\0')
i ;
if(z[i] != '\n')
z[i] = '\0';
else
while(getchar() != '\n')
continue;
}
return res;
}
Thank you for your understanding and helping me in understanding the concept in general. That code snippet is from Stephen Prata's C book, I modified it slightly.
CodePudding user response:
Assuming the declaration is char * wsklan[20];
.
In the expression &wsklan[0]
, []
takes precedence over &
, so we get pointer number 0. Then &
gives the address of that pointer. Since it's the first item in the array, you can assume it's the same address as obtained by &wsklan
.
In the expression &wsklan[0][0]
we also get pointer number 0, then again []
takes precedence over &
so we get character number 0
in the array that pointer number 0 points at. Then &
gives the address of that single character. What address that is depends on where you set the pointer to point at. It makes perfect sense that it points at a different address than where the pointer itself is stored. (Since a pointer pointing at its own address would be quite useless.)
Second question: wsklan[1]
is 100% equivalent to *(wsklan 1)
. So it has a different meaning than just wsklan 1
. Since the variable is of type "array of character pointers", it "decays" into a pointer to the first item when used in an expression. That would be a pointer to character pointer, char**
. That's not what printf expects - you'll have to de-reference it into a plain char*
first.
CodePudding user response:
For argument's sake, let us assume the following:
sizeof(char)
is 1 (by definition)sizeof(char *)
is 4 (e.g. on a system with 32-bit pointers)char data[20][300]
is stored at address 10000 (arbitrary)char *wsklan[20]
is stored at address 20000 (arbitrary)
Then:
&wsklan[0]
is converted to(char **)20000
&wsklan[1]
is converted to(char **)20004
&wsklan[2]
is converted to(char **)20008
Note: Unary
&
has lower precedence than[
]
, so&wsklan[0]
means&(wsklan[0])
.
and:
data[0]
and&data[0][0]
are converted to(char *)10000
data[1]
and&data[1][0]
are converted to(char *)10300
data[2]
and&data[2][0]
are converted to(char *)10600
Note:
&data[0][0]
means&((data[0])[0])
.
After:
wsklan[0] = data[0];
wsklan[1] = data[1];
then:
wsklan[0]
and&wsklan[0][0]
are converted to(char *)10000
(same asdata[0]
and&data[0][0]
)wsklan[1]
and&wsklan[1][0]
are converted to(char *)10300
(same asdata[1]
and&data[1][0]
)
Comparing &wsklan[0]
and &wsklan[0][0]
from above to summarize:
&wsklan[0]
is converted to(char **)20000
&wsklan[0][0]
is converted to(char *)10000
(same as&data[0][0]
)