在C中使用星号(* 运算符)的不同方式

kknvjkwl  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(130)

所以我知道 * 操作符用于乘法和作为指针,但有时我看到 * 操作符,我不确定它的意思。看看这个定义矩阵的代码

#ifndef MATRIX_H
#define MATRIX_H

/* The data structure representing a matrix */
typedef struct {
    int rows;       /* number of rows */
    int columns;    /* nuumber of columns */
    int **content;  /* matrix elements in a two dimensional array */
} matrix_t;

两个星号在这里是什么意思?
我假设**运算符用于二维数组中的指针,但我不确定。

ulydmbyx

ulydmbyx1#

多个间接寻址是一件事--你可以有指向指针的指针,指向指针的指针,指向指针数组的指针,指向指针数组的指针,指向指针数组的指针,指向指针数组的指针,指向返回指针的函数,等等。
此处使用的目的是分配一个指针数组:

matrix_t mat;
mat.content = calloc( 2, sizeof *mat.content );

这给了我们

int **     int *
             +---+      +---+
mat.content: |   | ---> |   | mat.content[0]
             +---+      +---+
                        |   | mat.content[1]
                        +---+

然后为每个指针分配一个int数组:

for ( size_t i = 0; i < rows; i++ )
  mat.content[i] = calloc( 2, sizeof *mat.content[i] );

给我们

int **     int *                     int
             +---+      +---+                     +---+
mat.content: |   | ---> |   | mat.content[0] ---> |   | mat.content[0][0]
             +---+      +---+                     +---+
                        |   | mat.content[1] -+   |   | mat.content[0][1]
                        +---+                 |   +---+
                                              |       
                                              |   
                                              |   +---+
                                              +-> |   | mat.content[1][0]
                                                  +---+
                                                  |   | mat.content[1][1]
                                                  +---+
  • 表达式 * mat.content具有类型int **,因此表达式*mat.content具有类型int *;类似地,表达式mat.content[i]也具有类型int **p == p[0]),所以*mat.content[i]具有类型int,所以sizeof *mat.content[i] == sizeof (int)

由于数组下标的工作方式,mat.content[i][j]的工作方式与将mat.content声明为int的常规二维数组完全相同,只不过不是将所有行分配到一个连续的块中,而是逐行分配。
一般规则:

T *p;        // p is a pointer to T
T *ap[N];    // ap is an array of pointer to T
T (*pa)[N];  // pa is a pointer to an array of T
T *fp();     // fp is a function that returns pointer to T
T (*pf)();   // pf is a pointer to a function that returns T

T **p;       // p is a pointer to a pointer to T
T ***p;      // p is a pointer to a pointer to a pointer to T

const T *p;  // p is a pointer to const T - you can write to p, but not *p
T const *p;  // same as above
T * const p; // p is a const pointer to T - you can write to *p, but not to p

当在 expression 中使用时,*会“取消引用”指针-如果您有类似于

int x;
int *p = &x;
  • 表达式 * *p充当x的一种别名:
*p = 10; // does the same thing as x = 10;

对象p存储x的位置,表达式p的类型为int *表达式*p等价于表达式x-它不仅产生存储在x中的值,您可以将新值写入x * 到 * *p,如上所示。
上述声明给予了以下关系:

p == &x // int * == int *
*p ==  x // int   == int

数组下标表达式a[i] * 定义 * 为*(a + i)-给定由a指定的起始地址,从该地址偏移i个元素(* 不是字节!*),并解引用结果。

*p == *(p + 0) == p[0]

数组不是指针,也不存储指向其第一个元素的指针。除非它是sizeof_Alignof或一元&运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则类型为“T的N元素数组“的表达式将被转换或“decay”,类型的表达式“指向T的指针“,表达式的值将是第一个元素的地址。这一点很重要-如果您声明一个数组

int a[10];

a不存储到其第一元素的地址;相反,每当编译器在上面列出的上下文之外看到 expressiona时,它基本上会将其替换为与&a[0]等效的内容。

相关问题