c - 当数组是另一个函数的形式参数时,函数参数中 typedef 常量大小数组的地址会导致指针类型不兼容

标签 c arrays pointers typedef

我已阅读 this thread并四处搜索更多信息,但大多数人只是说“不要像这样使用 typedef”。这种做事方式很吸引我,而且我也在尝试学习新事物,所以我想坚持下去。

我使用的是 gcc 版本 9.2.1

这是我正在做的事情的最小可重现示例:

#define TABLE_SZ 10

typedef int vec_t[3];

typedef struct {
    vec_t table_one[TABLE_SZ];
} tables;

void foo(vec_t * foo_vec) {
  (*foo_vec)[0] = 0;
}

void bar (tables bar_table, vec_t bar_vec) {
  foo(&(bar_table.table_one[0]));
  foo(&bar_vec);
}


int main() {
  vec_t vector;
  foo(&vector);
}
/home/happy/CLionProjects/os_2019_p5/tests/test_array_typedef_ops.c: In function ‘bar’:
/home/happy/CLionProjects/os_2019_p5/tests/test_array_typedef_ops.c:18:7: warning: passing argument 1 of ‘foo’ from incompatible pointer type [-Wincompatible-pointer-types]
   18 |   foo(&bar_vec);
      |       ^~~~~~~~
      |       |
      |       int **
/home/happy/CLionProjects/os_2019_p5/tests/test_array_typedef_ops.c:12:18: note: expected ‘int (*)[3]’ but argument is of type ‘int **’
   12 | void foo(vec_t * foo_vec) {
      |          ~~~~~~~~^~~~~~~

我认为这与“指针衰减”有关,我想将 bar_vec 转换为 int ** 吧? 具体来说,为什么 bar_vec 是 int ** 时 &(bar_table.table_one[0]) int (*)[3] 的类型?

我显然不想抑制 gcc 中所有不兼容的指针类型警告。
转换指针似乎是一件杂事。 我想保留 typedef。我不想将它隐藏在结构中。

是否有编译器标志或其他解决方案来告诉编译器按照我的预期处理这种情况? 我应该了解更多关于此的信息吗?

谢谢。

附:堆栈溢出是否有漂亮的编译器输出打印?

最佳答案

void bar (tables bar_table, vec_t bar_vec) 在很多方面都很糟糕:

  • 如果函数位于不同的翻译单元中,则按值传递结构非常低效并且无法被编译器优化。
  • typedef vec_t 不会阻止数组类型在作为参数传递时进行调整(“衰减”),因此 vec_t bar_vec 相当于 int*。因此,该数组不是通过值传递,而只是通过其地址传递。

编译器错误的原因是这样的:foo(&bar_vec);。您传递一个指向隐藏在 typedef 下的 int* 的指针,这意味着您传递一个 int**。然而,该函数需要一个 vec_t *,即 int(*)[3] 类型的数组指针。这就是编译器告诉您的内容。

没有编译器标志来解决这个问题,因为代码没有任何意义。通过删除 typedef 来解决这个问题,然后重写代码。

关于c - 当数组是另一个函数的形式参数时,函数参数中 typedef 常量大小数组的地址会导致指针类型不兼容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58683406/

相关文章:

迭代时更改二维数组的大小

c - execve 不接受环境参数

c - C语言分离输出数据

c - 在 C 中编写泛型函数,如何处理字符串

c - 通过指针打印文本

c++ - 0xC0000005 : Access violation reading location of an Integer?

c - 没有编译错误、结构和二维数组问题,而且我从未到达第二个打印语句?

c++ - 在文件描述符上设置 FD_CLOEXEC 与将其传递给 posix_spawn_file_actions_addclose 之间有区别吗?

ruby - 用 7n +1 填充 ruby​​ 中的数组

Java:为数组赋值