开发者

In C, what does a variable declaration with two asterisks (**) mean?

I am working with C and I'm a bit rusty. I am aware that * has three uses开发者_如何转开发:

  1. Declaring a pointer.
  2. Dereferencing a pointer.
  3. Multiplication

However, what does it mean when there are two asterisks (**) before a variable declaration:

char **aPointer = ...

Thanks,

Scott


It declares a pointer to a char pointer.

The usage of such a pointer would be to do such things like:

void setCharPointerToX(char ** character) {
   *character = "x"; //using the dereference operator (*) to get the value that character points to (in this case a char pointer
}
char *y;
setCharPointerToX(&y); //using the address-of (&) operator here
printf("%s", y); //x

Here's another example:

char *original = "awesomeness";
char **pointer_to_original = &original;
(*pointer_to_original) = "is awesome";
printf("%s", original); //is awesome

Use of ** with arrays:

char** array = malloc(sizeof(*array) * 2); //2 elements

(*array) = "Hey"; //equivalent to array[0]
*(array + 1) = "There";  //array[1]

printf("%s", array[1]); //outputs There

The [] operator on arrays does essentially pointer arithmetic on the front pointer, so, the way array[1] would be evaluated is as follows:

array[1] == *(array + 1);

This is one of the reasons why array indices start from 0, because:

array[0] == *(array + 0) == *(array);


C and C++ allows the use of pointers that point to pointers (say that five times fast). Take a look at the following code:

char a;
char *b;
char **c;

a = 'Z';
b = &a; // read as "address of a"
c = &b; // read as "address of b"

The variable a holds a character. The variable b points to a location in memory that contains a character. The variable c points to a location in memory that contains a pointer that points to a location in memory that contains a character.

Suppose that the variable a stores its data at address 1000 (BEWARE: example memory locations are totally made up). Suppose that the variable b stores its data at address 2000, and that the variable c stores its data at address 3000. Given all of this, we have the following memory layout:

MEMORY LOCATION 1000 (variable a): 'Z'
MEMORY LOCATION 2000 (variable b): 1000 <--- points to memory location 1000
MEMORY LOCATION 3000 (variable c): 2000 <--- points to memory location 2000


It declares aPointer as a pointer to a pointer to char.

Declarations in C are centered around the types of expressions; the common name for it is "declaration mimics use". As a simple example, suppose we have a pointer to int named p and we want to access the integer value it's currently pointing to. We would dereference the pointer with the unary * operator, like so:

x = *p;

The type of the expression *p is int, so the declaration of the pointer variable p is

int *p;

In this case, aPointer is a pointer to a pointer to char; if we want to get to the character value it's currently pointing to, we would have to dereference it twice:

c = **aPointer;

So, going by the logic above, the declaration of the pointer variable aPointer is

char **aPointer;

because the type of the expression **aPointer is char.

Why would you ever have a pointer to a pointer? It shows up in several contexts:

  • You want a function to modify a pointer value; one example is the strtol library function, whose prototype (as of C99) is
    long strtol(const char * restrict str, char ** restrict ptr, int base);  
    
    The second argument is a pointer to a pointer to char; when you call strtol, you pass the address of a pointer to char as the second argument, and after the call it will point to the first character in the string that wasn't converted.

  • Remember that in most contexts, an expression of type "N-element array of T" is implicitly converted to type "pointer to T", and its value is the address of the first element of the array. If "T" is "pointer to char", then an expression of type "N-element array of pointer to char" will be converted to "pointer to pointer to char". For example:
    
        void foo(char **arr)
        {
          size_t i = 0;
          for (i = 0; arr[i] != NULL; i++)
            printf("%s\n", arr[i]);
        }
    
        void bar(void)
        {
          char *ptrs[N] = {"foo", "bar", "bletch", NULL};
          foo(ptrs); // ptrs decays from char *[N] to char **
        }
    
    

  • You want to dynamically allocate a multi-dimensional array:
    
    #define ROWS ...
    #define COLS ...
    ...
    char **arr = malloc(sizeof *arr * ROWS);
    if (arr)
    {
      size_t i;
      for (i = 0; i < ROWS; i++)
      {
        arr[i] = malloc(sizeof *arr[i] * COLS);
        if (arr[i])
        {
          size_t j;
          for (j = 0; j < COLS; j++)
          {
            arr[i][j] = ...;
          }
        }
      }
    }
    


It means that aPointer points to a char pointer.

So

aPointer: pointer to char pointer

*aPointer :pointer to char

**aPointer: char

An example of its usage is creating a dynamic array of c strings

char **aPointer = (char**) malloc(num_strings);

aPointer gives you a char, which can be used to represent a zero-terminated string.

*aPointer = (char*)malloc( string_len + 1); //aPointer[0]
*(aPointer + 1) = (char*)malloc( string_len + 1); //aPointer[1]


This is a pointer to a pointer to char.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜