Home > front end >  (*(char **)(void *)&"a")[0] created memory error - pointer problem
(*(char **)(void *)&"a")[0] created memory error - pointer problem

Time:12-22

I have been working on trying to write a function that does string comparison for a generic binary search function. However, while writing the function, I realized that my pointer dereferencing does not work.

In essence, this is what doesn't work:

printf("***a[0] = %c\n", (*(char **)(void *)&"a")[0]);

I ran the debugger which tells me EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

However, this extremely similar code (which I believe to be identical to my previous code) does work.

char * stringa = "a";
printf("***stringa[0] = %c\n", (*(char **)(void *)&stringa)[0]);

I don't understand why the second one works but the first one doesn't. My understanding is that both "a" and stringa both represent the memory address of the beginning of a character array.

Thank you in advance.

CodePudding user response:

Pointers are not arrays. Arrays are not pointers.

  • &stringa results in a pointer to pointer of type char**.
  • &"a" results in an array pointer of type char(*)[2]. It is not compatible with char**.

You try to de-reference the char(*)[2] by treating it as a char** which won't work - they are not compatible types and in practice the actual array pointer is saying "at address x there is data" but when converting it you say "at address x there is a pointer".

If you try to print printf("%p\n", *(char **)(void *)&"a"); you don't get an address but data. I get something like <garbage> 0061 which is a little endian machine trying to convert the string into a larger integer number. In memory you'll have 0x61 ('a')then 0x00 (null term) - the string itself, not an address which you can de-reference.

CodePudding user response:

First, check this rule [emphasis added]:

3 Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ''array of type'' is converted to an expression with type ''pointer to type'' that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

From String literals [emphasis added]:

Constructs an unnamed object of specified character array type in-place, used when a character string needs to be embedded in source code.

Lets decode this first:

char * stringa = "a";
printf("***stringa[0] = %c\n", (*(char **)(void *)&stringa)[0]);

In this statement char * stringa = "a";, string "a" will convert to pointer to type char that points to the initial element of the string "a". So, after initialisation, stringa will point to first element of string literal "a".

&stringa is of type char **. Dereferencing it will give char * type which is nothing but string "a" and applying [0] to it will give character 'a'.

Now, lets decode this:

printf("***a[0] = %c\n", (*(char **)(void *)&"a")[0]);

Since, here you are giving unary operator & so, in this expression, (*(char **)(void *)&"a")[0], string "a" will not convert to pointer to its initial element and &"a" will give the pointer of type const char (*)[2] and that pointer will be type casted to char ** type.

Dereferencing this pointer will give first character of string "a" (i.e. 'a') which it will think of as a pointer of type char (because of type casting char **) and applying [0] to it. That means, it's trying to do something like this ((char *)0x0000000000000061)[0] (0x61 is hex value of character 'a') which is resulting in the error EXC_BAD_ACCESS.

Instead, you should do

printf("***a[0] = %c\n", (*(const char (*)[2])(void *)&"a")[0]);
  • Related