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)
Ответы
Ответ 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.