对c指针赋值有些困惑

having some confusion about c pointer assignment

我在思考 C 中的指针赋值时遇到了一些麻烦。星号字符出现在许多不同的位置,我不明白为什么我会选择使用一种方式而不是另一种方式。

具体在下面的代码中:

我为什么会选择:

conn->db->rows = (struct Address**)malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);

超过:

conn->db->rows = (struct **Address)malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);

在 sizeof 中,星号表示什么?

这就是上面代码的由来。不是整个程序。

struct Address {
  int id;
  int set;
  char *name;
  char *email;
};

struct Database {
  int MAX_DATA;
  int MAX_ROWS;
  struct Address **rows; // USE ARRAY OF POINTERS
};

struct Connection {
  FILE *file;
  struct Database *db;
};

void die(const char *message) {
  if(errno) {
    perror(message);
  } else {
    printf("ERROR: %s\n", message);
  }

  exit(1);
}

void Address_print(struct Address *addr) {
  printf("%d %s %s\n", addr->id, addr->name, addr->email);
}

void Database_load(struct Connection *conn) {
  size_t i=0;

  // Each database will have two `int` values. read
  // those first.
  assert(conn->db && conn->file);
  if (!(conn->db && conn->file))
      die("Database load : Invalid Connection info");
  if (fread(&conn->db->MAX_DATA, sizeof(conn->db->MAX_DATA), 1, conn->file) != 1)
      die("Database load : Couldn't read MAX_DATA");
  if (fread(&conn->db->MAX_ROWS, sizeof(conn->db->MAX_ROWS), 1, conn->file) != 1)
      die("Database load : Couldn't read MAX_ROWS");
  conn->db->rows = (struct Address**)malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);

  assert(conn->db->rows);
  if (!(conn->db->rows)) {
    die("Database_load : Could not MAX_ROWS Address  structures");
  }

struct **Address 是非法语法。基本类型是 struct Address,在 struct 关键字和 标签 Address 之间应该只有空格(注释算作空格)。

struct Address * 是一个指向 struct Address.

的类型

struct Address ** 是一个指向 struct Address.

的指针的类型

sizeof 表达式确定类型的大小(以字节为单位)。有两种形式:

  • sizeof(type)(对于某些类型,type)直接指定类型。
  • sizeof expression(对于某些表达式,expression)使用结果类型 expression 而不评估 expression.

sizeof(struct Address *)的情况下,使用第一种形式。这被评估为 struct Address * 类型(指向 struct Address 的指针)的大小(以字节为单位)。

在声明中:

conn->db->rows = (struct Address**)malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);

调用 malloc 的结果是一个通用指针类型 void * 并且它被 cast 运算符 (struct Address**) 以匹配分配给 rows 成员的类型。

在 C 中,通常的做法是在将 void * 值分配给另一个对象指针类型时省略强制转换,反之亦然。该语句可以重写,省略转换,如:

conn->db->rows = malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);

此外,sizeof(type)type 操作数可以用具有以下表达式的表达式替换同一类型。由于 conn->db->rows 的类型为 struct Address**,因此 *conn->db->rowsconn->db->rows[0] 的类型为 struct Address *。这些中的任何一个都可以替换到语句中,将其重写为,例如:

conn->db->rows = malloc(sizeof(*conn->db->rows) * conn->db->MAX_ROWS);

这比直接在 sizeof 表达式中指定类型更不容易出错,并且是常见的做法。