Подтвердить что ты не робот

Unsigned char автоматически повышается до int в вызове функции, почему?

Почему при вызове функции unsigned char автоматически присваивается int? В приведенном ниже примере есть функция f(int) и a f(char). Казалось логичнее, что компилятор будет принуждать аргумент unsigned char к char и вызывать f(char), так как они имеют одинаковое количество бит. Он вызывает f(int) вместо этого, даже если это означает продвижение аргумента к типу с большим количеством бит. Любые указатели на то, где определено правило? Стандартный или компилятор/платформа?

#include <iostream>

void f( int key )
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

void f( char key )
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main( int argc, char* argv[] )
{
    int a = 'a';
    char b = 'b';
    unsigned char c = 'c';

    f(a);
    f(b);
    f(c);

    return 0;
}

Производит этот вывод:

void f(int)
void f(char)
void f(int)
4b9b3361

Ответ 1

Потому что unsigned char не может быть представлен char. Например, если они оба являются 8 битами, а ваш unsigned char содержит значение 255, которое переполняет переполнение signed char - и подпись целых чисел вызывает поведение undefined. В любом случае, печатные символы обычно должны храниться в char, а не unsigned char (а строки C имеют тип char[], а не unsigned char[] и т.д.)

Таким образом, продвижение до int необходимо для представления значений больше 1 << (CHAR_BIT - 1).

Ответ 2

Я считаю, что правильный вывод из Стандарта основан на параграфе ниже, который находится в разделе 13.3.3. Лучшие жизнеспособные функции, т.е. часть (очень сложных) правил для разрешения перегрузки функции.

(§13.3.3.2/4) Стандартные последовательности преобразования упорядочены по их рангу: Точное совпадение - лучшее преобразование, чем Продвижение, которое является лучшим преобразованием, чем Конверсия. Две последовательности преобразований с одинаковым рангом неразличимы, если не применяется одно из следующих правил: [...]

Преобразование unsigned char в int классифицируется как продвижение (определено в п. 4.5, при чтении ниже, обратите внимание, что (unsigned) char является целым типом):

§4.5 Интегральные акции
[...]

(§4.5/2) PRvalue целочисленного типа, отличного от bool, char16_t, char32_t или wchar_t, чей целочисленный ранг преобразования (4.13) меньше ранга int может быть преобразован в prvalue типа int, если int может представлять все значения типа источника; в противном случае исходное значение prvalue может быть преобразовано в prvalue типа unsigned int.

В то время как преобразование unsigned char в char не классифицируется как продвижение, потому что их ранги идентичны:

(§4.13/1) [...] Ранг char должен равняться рангам подписанных char и unsigned char. [...]

Вместо этого он классифицируется как интегральное преобразование (§4.7), и, как описано выше, продвижение предпочтительнее преобразования при разрешении перегрузки.

Ответ 3

В стандарте С++ char не определяется как unsigned или signed (хотя размер 1 байт), поэтому его реализация определена. Поэтому в вашей реализации я считаю, что он подписал char, почему он получил повышение.

Ответ 4

int и char просто различаются по диапазону в C и С++, если char он находится в диапазоне от 0 до 255, а если int, он имеет свой диапазон как 65535 (диапазон значений int зависит от ОС). Поэтому компилятор просто рассматривает его как int.