У меня есть очень простой код на C ++:

#include <iostream>
int main() {
    std::cout << (int)(char)(int)char(-2);
    return 0;
}

Я выполняю его в разных настройках:

  • Ubuntu 20.04 x64 (g ++) -> Вывод: -2
  • Windows 10 x64 MSVC 2017 -> Вывод: -2
  • MacOS x64 Clang -> Выход -2
  • Ubuntu Armv8 (g ++) / Экземпляр EC2 -> Вывод: 254

Я все время хочу получить -2 и не понимаю этой разницы в поведении.

Есть у кого-нибудь идеи?

2
BlackPopa 2 Май 2021 в 23:38

3 ответа

Лучший ответ

Компилятору разрешено выбирать, подписан ли char или нет. Стандарт говорит, что они должны выбирать, но не требует, какой путь они выберут.

GCC поддерживает -fsigned-char и -funsigned-char, чтобы заставить это поведение.

4
Bill Lynch 2 Май 2021 в 20:43

Из международного стандарта ISO C ++ (Наконечник ствола):

§6.8.2 Основные типы [basic.fundamental]

7 - Тип char - это отдельный тип, для которого в зависимости от реализации выбирается «signed char» или «unsigned char» в качестве базового типа .

[...]

Больше нечего добавить по этому поводу.

Производители компиляторов могут выбирать тот, который им нравится или кажется более разумным с учетом целевой архитектуры, для архитектур ARM кажется этот беззнаковый символ предпочтительнее.

Возник вопрос: почему? В найденном мной обосновании упоминается, что причина этого заключается в том, что более старые версии ARM, до ARMv4, не имели встроенной поддержки для загрузки полуслов и подписанных байтов, поэтому char стал по умолчанию unsigned, а { {X2}} остается.

Главный источник:

http://www.davespace.co.uk/arm/efficient-c-for-arm/memaccess.html

2
anastaciu 2 Май 2021 в 22:48

Показанный результат согласуется с тем, что char является беззнаковым типом данных на рассматриваемой платформе. Стандарт C ++ позволяет char быть эквивалентным unsigned char или signed char.

Если вам нужно определенное поведение, вы можете явно использовать приведение к signed char в своем коде.

0
Sam Varshavchik 2 Май 2021 в 20:41