Несовместимый указатель, когда int и long совпадают? - PullRequest
1 голос
/ 09 апреля 2020

При компиляции C для платформы, где int и long имеют значение 32 бита, а long long - 64 бита (например, clang или g cc -m32 или цель wasm32-unknown-wasi clang), я получаю ошибки о несовместимых типах указателей:

int32_t *i1 = NULL;
long *l1 = i1;
int64_t *i2 = NULL;
long *l2 = i2;
sizeof.c:13:11: warning: incompatible pointer types initializing 'long *' with an expression of type 'int32_t *' (aka 'int *') [-Wincompatible-pointer-types]
    long *l1 = i1;
          ^    ~~
sizeof.c:15:11: warning: incompatible pointer types initializing 'long *' with an expression of type 'int64_t *' (aka 'long long *') [-Wincompatible-pointer-types]
    long *l2 = i2;
          ^    ~~
2 warnings generated.

Мне кажется странным, что ни int32_t, ни int64_t не совместимы с long. Почему появляется предупреждение, если int и long совпадают?

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

Правила C о том, что делает типы совместимыми, частично касаются «значения» типа, а не только того, насколько он велик, какие значения он представляет или как он их представляет. В этих правилах указатели на int и long являются разными и несовместимыми типами, даже если они используют одинаковое количество байтов и одинаково кодируют адреса и указывают на int и long, которые используют одинаковое количество байтов и кодировать числа таким же образом.

Стандарт C может разрешить реализацию C для определенных (typedef) int32_t и int64_t значений int, long или long long, в зависимости от ситуации. В этом случае соответствующие типы будут не только совместимыми, но и идентичными. Однако стандарт также позволяет определять их как расширенные типы, отличные от целочисленных типов c, даже если они функционируют одинаково. Как отмечает chqrl ie, ваша реализация C, вероятно, определяет int32_t как int и int64_t как long long, поэтому ни один из них не совместим с long.

«Значение» типа включает в себя некоторые вещи о том, для чего люди планируют использовать тип и что это значит для компилятора. int первоначально означало, что размер с целевым процессором в некотором смысле хороший, но со временем он ослаб. Два типа структуры могут быть определены с одинаковыми элементами, но один содержит координаты xy для двумерного графа, а другой содержит вещественно-мнимые части для комплексных чисел. Наличие этих отдельных и несовместимых типов помогает программистам избежать некоторых ошибок.

В целом код, такой как int32_t x; int *p = &x;, был написан с ошибкой, и желательно указать на это предупреждение. И предупреждение не является помехой, так как легко написать код, который работает, как нужно, без получения предупреждения.

0 голосов
/ 09 апреля 2020

Причина, по которой long * не совместим ни с int32_t *, ни с int64_t *, заключается в том, что эти типы определены на вашей платформе следующим образом:

typedef int int32_t;
typedef long long int int64_t;`

Стандартные типы int, длинные and long long` отличаются, даже если они имеют одинаковый размер и / или представление.

В стандарте C нет ничего, что предписывало бы использовать или int, long и long long для целых чисел указанного размера при условии, что одно из них соответствует его количеству битов и двум требованиям представления дополнения. int32_t можно даже определить как отдельный расширенный тип с соответствующим ранжированием.

Вы должны использовать правильные типы указателей в своем коде и избегать предположений о фактическом представлении базовых c целочисленных типов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...