在C中,带有两个星号(**)的变量声明是什么意思?

Sco*_*ies 37 c pointers

我和C一起工作,我有点生疏了.我知道它*有三个用途:

  1. 声明一个指针.
  2. 取消引用指针.
  3. 乘法

但是,**在变量声明之前有两个星号()时它意味着什么:

char **aPointer = ...
Run Code Online (Sandbox Code Playgroud)

谢谢,

斯科特

Jac*_*kin 32

它声明了一个char指针指针.

这种指针的用法是做以下的事情:

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
Run Code Online (Sandbox Code Playgroud)

这是另一个例子:

char *original = "awesomeness";
char **pointer_to_original = &original;
(*pointer_to_original) = "is awesome";
printf("%s", original); //is awesome
Run Code Online (Sandbox Code Playgroud)

使用**数组:

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
Run Code Online (Sandbox Code Playgroud)

[]数组上的运算符基本上对前指针进行指针运算,因此,计算方式array[1]如下:

array[1] == *(array + 1);
Run Code Online (Sandbox Code Playgroud)

这是数组索引开始的原因之一0,因为:

array[0] == *(array + 0) == *(array);
Run Code Online (Sandbox Code Playgroud)

  • @Jacob - 是:有效的C语法?我不熟悉. (2认同)

Jef*_*son 28

C和C++允许使用指向指针的指针(比如快五倍).看看下面的代码:

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

a = 'Z';
b = &a; // read as "address of a"
c = &b; // read as "address of b"
Run Code Online (Sandbox Code Playgroud)

变量a包含一个字符.变量b指向内存中包含字符的位置.变量c指向内存中的一个位置,该位置包含指向内存中包含字符的位置的指针.

假设变量a将其数据存储在地址1000处(请注意:示例内存位置完全组成).假设变量b将其数据存储在地址2000,并且变量c将其数据存储在地址3000处.鉴于所有这些,我们有以下内存布局:

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
Run Code Online (Sandbox Code Playgroud)


Tom*_*Tom 5

这意味着aPointer指向一个字符指针。

所以

aPointer: pointer to char pointer

*aPointer :pointer to char

**aPointer: char
Run Code Online (Sandbox Code Playgroud)

其用法的一个示例是创建 c 字符串的动态数组

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

aPointer 为您提供一个 char,它可用于表示以零结尾的字符串。

*aPointer = (char*)malloc( string_len + 1); //aPointer[0]
*(aPointer + 1) = (char*)malloc( string_len + 1); //aPointer[1]
Run Code Online (Sandbox Code Playgroud)


Joh*_*ode 5

它声明aPointer为指向 char 的指针的指针。

C 语言中的声明以表达式类型为中心;它的通用名称是“声明模拟使用”。作为一个简单的例子,假设我们有一个指向 int 的指针,p并且我们想要访问它当前指向的整数值。我们将使用一元运算符取消引用指针*,如下所示:

x = *p;
Run Code Online (Sandbox Code Playgroud)

表达式 的类型*pint,所以指针变量的声明p

int *p;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,aPointer是一个指向 char 的指针的指针;如果我们想获得它当前指向的字符值,我们必须取消引用它两次:

c = **aPointer;
Run Code Online (Sandbox Code Playgroud)

所以,按照上面的逻辑,指针变量的声明aPointer

char **aPointer;
Run Code Online (Sandbox Code Playgroud)

因为表达式 的类型**aPointerchar.

为什么你会有一个指向指针的指针?它出现在几种情况下:

  • 你想要一个函数来修改一个指针值;一个例子是strtol库函数,它的原型(从 C99 开始)是
    long strtol(const char * restrict str, char ** restrict ptr, int base);  
    
    第二个参数是一个指向 char 指针的指针;当您调用 时strtol,您将指向 char 的指针的地址作为第二个参数传递,并且在调用之后它将指向字符串中未转换的第一个字符。

  • 请记住,在大多数上下文中,“T 的 N 元素数组”类型的表达式被隐式转换为“指向 T 的指针”类型,其值是数组第一个元素的地址。如果“T”是“指向 char 的指针”,那么类型为“指向 char 的指针的 N​​ 元素数组”的表达式将被转换为“指向指向 char 的指针的指针”。例如:
    
        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 **
        }
    
    

  • 你想动态分配一个多维数组:
    
    #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] = ...;
          }
        }
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)