Please take a look of snippet: I am not able to understand why code is giving segmentation fault and garbage characters.
#include <stdio.h>
int main()
{
char *str[1];
str[0] = "apple";
char **ptr = str;
char *p = str;
printf("%d\n", ptr); //---> 1956347328
printf("%d\n", p); //---> 1956347328
printf("%s \n", *ptr, ); // ---> prints apple
printf("%s\n", *p); // ---> error segmentation fault
printf("%s\n", p); // ---> Garbage characters
}
Here is a detailed explanation of the posted code behavior and problems:
char *str[1];defines an array of pointers tocharwith a single element.str[0] = "apple";might trigger a warning as you store a pointer to a string literal, which must not be modified, into an element of the array which contains pointer to modifiable data. As long as you do not use this pointer to actually try and modify the string, you are safe.char **ptr = str;defines another object, a pointer to a pointer tochar, intialized to point to the arraystr. No problem with that, but you can only access the element atptr[0].char *p = str;defined another object, a pointer tocharinitialized to point to the arraystr. This is a type mismatch as the type ofstris neither array ofcharnor pointer tochar, hence the compiler should issue a warning. Yet as long as you only use this pointer to access the bytes that compose this array, you are safe. The array contains a single pointer (that points to the"apple"string), which on your 64-bit machine is composed of 8 bytes.printf("%d\n", ptr)has undefined behavior becauseprintfexpects an argument of typeintfor the%dformat, and you pass achar **value. On your architecture, integers and pointers seem to be passed in the same register or stack area, soprintfoutputs an integer that is a part (the low 32 bits) of the pointer,1956347328. You should instead useprintf("%p\n", (void *)ptr);printf("%d\n", p)same remark as above, the output is the same because both pointers point to the same address, but as they have different types, dereferencing them produces different things.printf("%s \n", *ptr, )is a syntax error, but without the extra,printfreceives*ptr, which is the first element of the arraystr, ie: thechar *pointer to the string"apple", which is what it expects for%s.printfoutputs the stringapple, a space and a newline.printf("%s\n", *p):printfreceives*p, which is thecharat the beginning of thestrarray. This byte is the first byte of the pointer to the string, which has one of 256 possible values for such a pointer, in the rangeCHAR_MINtoCHAR_MAX(0..255 or -128..127 depending on the signedness of typechar).printfexpects a pointer tocharas the argument for the%sconversion. Passing thecharvalue has undefined behavior, and the value used byprintfin your case is an invalid pointer: dereferencing it causes a segmentation fault.printf("%s\n", p): the pointerpis passed toprintffor the%sconversion, which is fine, butprintfreads and outputs the bytes it points to until it reads a null byte. These bytes are not those of the stringapple, they are the bytes that compose the pointer stored instr[0], which look like garbage values when output as characters. Ifprintfdid not find a null byte as it reads them, it would invoke undefined behavior whren reading past the end of the array and possibly cause a segmentation fault too.Consider this modified version:
I get this output on my macbook:
If I run the same executable again, I get different output because of address space randomisation, a technique used to make it more difficult for hackers to exploit software vulnerabilities.
The output shows that:
the 3 objects
p,ptrandstrhave a size of 8 bytes.they are located in memory in adjacent places (in stack, below the
mainarguments).pandptrpoint to the area occupied bystr: the address0x3085b8280is stored in little endian order, ie: from the least significant byte to the most significant byte. This looks like reverse order but the order in which to store the bytes of a pointer (or integer) is only a matter of convention, just like the order of parts of speech in a phrase vary from one language to another.the string
"apple"which contains the bytes61 70 70 6c 65 00is located at address0x1023dff58(a constant data segment).*phas the value6bwhich is ak, but, on my laptop, this value varies from one run to another as explained here above.