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 *)10000data[1]and&data[1][0]are converted to(char *)10300data[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])
