Адрес массива постоянного размера typedef в аргументе функции вызывает несовместимые типы указателей, когда массив является формальным параметром другой функции - PullRequest
0 голосов
/ 03 ноября 2019

Я прочитал эту тему и искал дополнительную информацию, но большинство людей просто говорят: "Не используйте typedefs, как это". Этот способ работы мне нравится, и я также пытаюсь изучать новые вещи, поэтому я хочу придерживаться этого.

Я использую 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_table.table_one [0]) int (*) [3], когда bar_vec имеет тип int **?

Я явно не хочу подавлять все предупреждения о несовместимых типах указателей вgcc.
Приведение указателя кажется клуджем. Я хочу сохранить typedef. Я не хочу скрывать это в структуре.

Есть ли флаг компилятора или другое решение, чтобы сказать компилятору, чтобы я воспринимал эту ситуацию так, как я ожидаю? Есть ли еще информация по этому вопросу, о которой я должен знать?

Спасибо.

ps имеет ли переполнение стека красивую печать для вывода компилятора?

1 Ответ

1 голос
/ 03 ноября 2019

void bar (tables bar_table, vec_t bar_vec) плохо во многих отношениях:

  • Вы передаете структуру по значению, которое очень неэффективно, и не может оптимизироваться компилятором, если функция находится вдругой переводчик.
  • * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *) typedef vec_t не препятствует корректировке типа вашего массива («затухания») при передаче в качестве параметра, поэтому vec_t bar_vec эквивалентно int*. И поэтому этот массив не передается по значению, только по его адресу.

Однако причина ошибки компилятора такова: foo(&bar_vec);. Вы передаете указатель на int*, который вы скрыли под typedef, что означает, что вы передаете int**. Функция, однако, ожидает vec_t *, что означает указатель массива типа int(*)[3]. Это то, что говорит вам компилятор.

Нет флага компилятора, чтобы решить эту проблему, потому что код не имеет никакого смысла. Решите это, избавившись от typedef, затем перепишите код.

...