https://i.stack.imgur.com/7Fgkp.jpg output)this the link for image of output
my code ---->
#include <stdio.h>
const int MAX = 5;
int main () {
char *names[] = {
"Zara Ali",
"Hina Ali",
"Nuha Ali",
"Sara Ali",
"Zara Ali"
};
int i = 0;
for ( i = 0; i < MAX; i ) {
printf("Value of *names[%d] = %c char\n", i, *names[i] );
}
for ( i = 0; i < MAX; i ) {
printf("Value of *(names %d) = %d\n", i, *(names i) );
}
for ( i = 0; i < MAX; i ) {
printf("Value of names[%d] = %d\n", i, names[i] );
}
for ( i = 0; i < MAX; i ) {
printf("Value of *(names %d) = %s\n", i, *(names i) );
}
for ( i = 0; i < MAX; i ) {
printf("Value of names[%d] = %s\n", i, names[i] );
}
printf("Value of names = %d\n",names );
printf("Value of names 1 = %d\n",names 1 );
return 0;
}
when value of names
and names[0]
is not same.
where can i learn this topic properly.
the problem is "i don't know that .. which variable is storing which adress or value".
CodePudding user response:
First of all, the following line is wrong:
printf("Value of names = %d\n",names );
Using the %d
format specifier is not the correct way to print a pointer. Although it may work on most 32-bit platforms (on which pointers normally have a size of 4
), it will most certainly not work properly on 64-bit platforms (on which pointers normally have a size of 8
).
The correct way to print a pointer is using the %p
format specifier and by casting the pointer to void*
:
printf( "Value of names = %p\n", (void*)names );
On most platforms, the cast to void*
is not necessary, so you can probably safely omit it (even if ISO C formally requires the cast).
As already pointed out in the comments section, writing names[i]
is, by definition, equivalent to writing *(names i)
.
The reason why the difference between names
and names 1
is 8
is because in both expressions, the array names
decays to a pointer to its first element, i.e. to &names[0]
. Incrementing a pointer by 1
does not increase the address by 1
, but rather makes it point to the next element. Since each element of the array names
is a pointer and seems to have a size of 8
on your platform (you seem to be on a 64-bit platform with 64-bit pointers), the address is incremented by 8
when you increment the pointer by 1
.
In your picture, you seem to also be asking why the difference between *(names 0)
and *(names 1)
is 9
. The expression *(names 0)
is equivalent to names[0]
, which is a pointer to the string literal "Zara Ali"
. The expression *(names 1)
is equivalent to names[1]
, which is a pointer to the string literal "Hina Ali"
. So both of these expressions represent addresses of string literals, i.e. addresses of where the compiler is storing a certain string literal. Where compilers store string literals is up to the compiler to decide and compilers may behave differently. However, in this case, it seems that the compiler decided to store both string literals next to each other in memory. The string literal "Zara Ali"
has a length of 9
(including the null terminating character), so that explains why the difference in the addresses is 9
.
CodePudding user response:
Pictures will help:
char * char
––– –––
| | names[0] ––––> |'Z'| names[0][0]
––– –––
| | names[1] –– |'a'| names[0][1]
––– | –––
... | ...
| –––
| |'i'| names[0][7]
| –––
| | 0 | names[0][8]
| –––
|
| –––
-> |'H'| names[1][0]
–––
|'i'| names[1][1]
–––
...
–––
|'i'| names[1][7]
–––
| 0 | names[1][8]
———
Each string literal ("Zara Ali"
, "Hina Ali"
, etc.) is stored as a zero-terminated array of char
somewhere in memory (string literals are stored in such a way that they are available over the lifetime of the program).
Each names[i]
stores the address of the first character of each string literal.
The expression names
has type "pointer to pointer to char
" (char **
)1 and evaluates to the address of the first element of the names
array - it’s equivalent to writing &names[0]
. The expression names[0]
evaluates to the address of the first character in the "Zara Ali"
string literal - it’s the same as writing &names[0][0]
.
Use the %p
conversion specifier to print pointer values instead of %d
- %d
expects its corresponding argument to have type int
, and pointers are not integers:
printf( "Value of names[%d] = %p\n", i, (void *) names[i] );
printf( "Value of names = %p\n", (void *) names );
printf( "Value of names 1 = %p\n", (void *) (names 1) );
This is pretty much the only time you need to explicitly cast a pointer to void *
in C.
- Unless it is the operand of the
sizeof
or unary&
operators, or unless it is a string literal used to initialize an array of character type in a declaration, an expression of type "N-element array ofT
" will be converted, or "decay”, to an expression of type "pointer toT
" and the value of the expression will be the address of the first element of the array.
The variablenames
is declared as an array of pointer tochar
(char *[]
). However, whennames
appears in an expression and it is not the operand ofsizeof
or unary&
, it is converted to type "pointer to pointer tochar
(char **
).
This is whynames
is an array ofchar *
- each of the string literals is itself an array expression ("9-element array ofchar
"), but in this context "decays" to typechar *
.