Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I access a pointer to pointer for a stack array?

Tags:

c

Please take a look at the following code. It tries to pass an array as a char** to a function:

#include <stdio.h> #include <stdlib.h>  static void printchar(char **x) {     printf("Test: %c\n", (*x)[0]); }  int main(int argc, char *argv[]) {     char test[256];     char *test2 = malloc(256);      test[0] = 'B';     test2[0] = 'A';      printchar(&test2);            // works     printchar((char **) &test);   // crashes because *x in printchar() has an invalid pointer      free(test2);      return 0; } 

The fact that I can only get it to compile by explicitly casting &test2 to char** already hints that this code is wrong.

Still, I'm wondering what exactly is wrong about it. I can pass a pointer to a pointer to a dynamically allocated array but I can't pass a pointer to a pointer for an array on the stack. Of course, I can easily work-around the problem by first assigning the array to a temporary variable, like so:

char test[256]; char *tmp = test; test[0] = 'B'; printchar(&tmp); 

Still, can someone explain to me why it doesn't work to cast char[256] to char** directly?

like image 458
Andreas Avatar asked Feb 01 '20 12:02

Andreas


People also ask

How do you declare a pointer to an array of pointers to?

To declare a pointer to an array type, you must use parentheses, as the following example illustrates: int (* arrPtr)[10] = NULL; // A pointer to an array of // ten elements with type int. Without the parentheses, the declaration int * arrPtr[10]; would define arrPtr as an array of 10 pointers to int.

Can a pointer can point to an array?

C. In this program, we have a pointer ptr that points to the 0th element of the array. Similarly, we can also declare a pointer that can point to whole array instead of only one element of the array. This pointer is useful when talking about multidimensional arrays.

Why should one never return a pointer to something that is stack allocated?

Because it will cause undefined behavior in your program. Show activity on this post. If you return a pointer to a local variable once the function returns it is out of scope. From then on it is undefined behavior if you access the returned pointer.

Can pointers be on stack?

A stack pointer is a small register that stores the memory address of the last data element added to the stack or, in some cases, the first available address in the stack.


2 Answers

test is an array, not a pointer, and &test is a pointer to the array. It is not a pointer to a pointer.

You may have been told that an array is a pointer, but this is incorrect. The name of an array is a name of the entire object—all the elements. It is not a pointer to the first element. In most expressions, an array is automatically converted to a pointer to its first element. That is a convenience that is often useful. But there are three exceptions to this rule:

  • The array is the operand of sizeof.
  • The array is the operand of &.
  • The array is a string literal used to initialize an array.

In &test, the array is the operand of &, so the automatic conversion does not occur. The result of &test is a pointer to an array of 256 char, which has type char (*)[256], not char **.

To get a pointer to a pointer to char from test, you would first need to make a pointer to char. For example:

char *p = test; // Automatic conversion of test to &test[0] occurs. printchar(&p);  // Passes a pointer to a pointer to char. 

Another way to think about this is to realize that test names the entire object—the whole array of 256 char. It does not name a pointer, so, in &test, there is no pointer whose address can be taken, so this cannot produce a char **. In order to create a char **, you must first have a char *.

like image 149
Eric Postpischil Avatar answered Oct 13 '22 20:10

Eric Postpischil


Because test is not a pointer.

&test gets you a pointer to the array, of type char (*)[256], which is not compatible with char** (because an array is not a pointer). This results in undefined behavior.

like image 34
emlai Avatar answered Oct 13 '22 21:10

emlai