Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does dereferencing a char** value (pointer-to-pointer-to-char) differ from dereferencing a char*[] (pointer-to-char array)?

If a char* array is defined with at least one value, the first value can be indexed via "arr[0]" and printed successfully with the format specifier "%s". However, if a char** is defined, it will segfault if the first element is attempted to be printed with printf or similar functions (with string format specifier).

Below is a block of code that demonstrates how this works:

char* s = "test";
char** sa = { s };
char* arr[] = { s };

// Prints pointers of each variable
puts("\nTest 1:");
puts("----------------------------------------");
printf("s:\t%p\n", s);
printf("sa:\t%p\n\n", sa);

// Dereferences pointers, prints as pointers (even though *s is a char)
puts("Test 2:");
puts("----------------------------------------");
printf("s:\t%p\n", *s);
printf("sa:\t%p\n\n", *sa);

// Prints strings of each variable
puts("Test 3:");
puts("----------------------------------------");
printf("s:\t%s\n", s);
printf("sa:\t%s\n\n", sa);

// Prints first element of array (works unlike *(char**), which I would think are the same)
puts("Test 4:");
puts("----------------------------------------");
printf("arr:\t%s\n", arr[0]);
printf("arr:\t%s\n\n", *arr);

// Prints strings of dereferenced pointers (segfault for sa)
puts("Test 5:");
puts("----------------------------------------");
printf("s:\t%s\n", *s);
printf("sa:\t%s\n\n", *sa);

This is the potential output:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Test 1:
----------------------------------------
s:      0x10013bf2c
sa:     0x10013bf2c

Test 2:
----------------------------------------
s:      0x74
sa:     0x65540a0074736574

Test 3:
----------------------------------------
s:      test
sa:     test

Test 4:
----------------------------------------
arr:    test
arr:    test

Test 5:
----------------------------------------
zsh: segmentation fault  ./test2

I understand that dereferencing variable s returns the ASCII value for the first character, which is "t" in this case. However, I’m confused on why variable sa doesn’t dereference to the first string in the array? Shouldn’t dereferencing the double pointer return the pointer to s?

I’ve tried returning strings from the pointer sa returns, but it only segfaults, meaning that the pointer for sa under Test 2 has no meaning or association with the string bounded to s.

>Solution :

For starters you do not have an array. In this declaration

char** sa = { s };

you declared a pointer of the type char ** that is initialized by the value of the variable s of the type char *.

char* s = "test";
char** sa = { s };

The compiler should issue a message that there is no implicit conversion between these two pointer types.

The difference between these two outputs

printf("s:\t%p\n", *s);
printf("sa:\t%p\n\n", *sa);

is that in the first case the expression *s has the type char that is promoted to the type int. That is only the first byte of the string literal is read as a value.

In the second case the expression *sa is considered as an expression of the pointer type char *. So the function reads the memory occupied by the expression as a memory storing a pointer of the size 4 or 8 bytes depending on the used system without any promotions as in the first case.

As for your comment to my answer

Also, when the char* version of sa (when sa is dereferenced) is
attempted to be printed as a string using the format specifier "%s", a
segfault occurs. This is the main source of what I’m a bit
confused
about

When the pointer sa is dereferenced then its value is the value composed by characters stored in the string literal and this value is interpreted as a pointer when the conversion specifier %s is used. That of course results in undefined behavior.

See the output of the code you showed in your question

sa:     0x65540a0074736574

This part of the outputted value 74736574 represents the word "test" written in the reverse order "tset".

You could write instead

char* s = "test";
char** sa = { &s };

and then

printf( "%s\n", *sa );

In this case the pointer sa will contain the address of the declared pointer s and the expression *sa yields the value stored in the pointer s that is the address of the first character of the string literal "test".

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading