简体   繁体   English

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

[英]Address of typedef'd constant-sized array in function argument causes incompatible pointer types when array is another function's formal parameter

I've read this thread and searched around for more information but most people just say "don't use typedefs like this."我已阅读此线程并四处搜索以获取更多信息,但大多数人只是说“不要使用这样的 typedef”。 This way of doing things is appealing to me and I am also trying to learn new things, so I want to stick with this.这种做事方式对我很有吸引力,我也在努力学习新事物,所以我想坚持下去。

I'm using gcc version 9.2.1我正在使用 gcc 版本 9.2.1

Here is a minimum reproducible example of what I'm doing:这是我正在做的最小可复制示例:

#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) {
      |          ~~~~~~~~^~~~~~~

I assume this has something to do with "pointer decay", I guess bar converting bar_vec to int **?我认为这与“指针衰减”有关,我猜 bar 将 bar_vec 转换为 int **? Specifically, why is the type of &(bar_table.table_one[0]) int (*)[3] when bar_vec is int **?具体来说,当 bar_vec 为 int ** 时,为什么 &(bar_table.table_one[0]) int (*)[3] 的类型是?

I obviously don't want to supress all incompatible pointer type warnings in gcc.我显然不想在 gcc 中禁止所有不兼容的指针类型警告。
Casting the pointer seems like a kludge.铸造指针似乎是一个杂物。 I want to keep the typedef.我想保留typedef。 I don't want to hide it in a struct.我不想将它隐藏在结构中。

Is there a compiler flag or other solution to tell the compiler to treat this situation as I expect it to?是否有编译器标志或其他解决方案来告诉编译器按照我的预期处理这种情况? Is there more information on this I should be aware of?我应该注意这方面的更多信息吗?

Thank you.谢谢你。

ps does stack overflow have pretty printing for compiler output? ps 堆栈溢出是否对编译器 output 有漂亮的打印?

void bar (tables bar_table, vec_t bar_vec) is bad in many ways: void bar (tables bar_table, vec_t bar_vec)在很多方面都很糟糕:

  • You pass the struct by value which very ineffective and can't get optimized by the compiler if the function is in a different translation unit.如果 function 位于不同的翻译单元中,则按值传递结构非常无效并且无法由编译器优化。
  • The typedef vec_t doesn't prevent your array type from getting adjusted ("decay") upon getting passed as parameter, so vec_t bar_vec is equivalent to int* . typedef vec_t不会阻止您的数组类型在作为参数传递时得到调整(“衰减”),因此vec_t bar_vec等效于int* And this array is therefore not getting passed by value, just its address.因此,这个数组不是按值传递的,只是它的地址。

The reason for the compiler error is however this: foo(&bar_vec);然而,编译器错误的原因是: foo(&bar_vec); . . You pass a pointer to the int* you have hidden beneath the typedef, meaning that you pass an int** .你传递了一个指向你隐藏在 typedef 下的int*的指针,这意味着你传递了一个int** The function however, expects a vec_t * , meaning an array pointer of type int(*)[3] .然而,function 需要一个vec_t * ,这意味着一个int(*)[3]类型的数组指针。 This is what the compiler is telling you.这就是编译器告诉你的。

There is no compiler flag to solve this, because the code doesn't make any sense.没有编译器标志来解决这个问题,因为代码没有任何意义。 Solve this by getting rid of the typedef, then rewrite the code.通过摆脱 typedef 来解决这个问题,然后重写代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM