Добавление двух Chars производит Int
-
25-10-2019 - |
Вопрос
Я сделал простую программу и собрал ее с GCC 4.4/4.5 следующим образом:
int main ()
{
char u = 10;
char x = 'x';
char i = u + x;
return 0;
}
g ++ -c -wconversion a.cpp
И у меня есть следующее:
a.cpp: In function ‘int main()’:
a.cpp:5:16: warning: conversion to ‘char’ from ‘int’ may alter its value
То же самое предупреждение, которое у меня было для следующего кода:
unsigned short u = 10;
unsigned short x = 0;
unsigned short i = u + x;
a.cpp: In function ‘int main()’:
a.cpp:5:16: warning: conversion to ‘short unsigned int’ from ‘int’ may alter its value
Может ли кто -нибудь объяснить мне, почему добавление двух Chars (или двух беспинентных шортов) производит Int? Это ошибка компилятора или это стандартное соответствие?
Спасибо.
Решение
То, что вы видите, является результатом так называемых «обычных арифметических преобразований», которые происходят во время арифметических выражений, особенно те, которые носят бинарный характер (принимайте два аргумента).
Это описано в §5/9:
Многие бинарные операторы, которые ожидают операндов арифметического или типа перечисления, вызывают преобразования и типы результатов аналогичным образом. Цель состоит в том, чтобы дать общий тип, который также является типом результата. Этот шаблон называется Обычные арифметические преобразования, которые определены следующим образом:
- Если любой операнд типа
long double
, другой должен быть преобразован вlong double
.
- В противном случае, если любой операндdouble
, другой должен быть преобразован вdouble
.
- В противном случае, если любой операндfloat
, другой должен быть преобразован вfloat
.
- В противном случае, интегральные акции (4.5) должны выполняться на обоих операнде.54)
- тогда, если любой операндunsigned long
другой должен быть преобразован вunsigned long
.
- В противном случае, если один операндlong int
и другиеunsigned int
, тогда, еслиlong int
может представлять все значенияunsigned int
,unsigned int
должен быть преобразован вlong int
; в противном случае оба операнда должны быть преобразованы вunsigned long int
.
- В противном случае, если любой операндlong
, другой должен быть преобразован вlong
.
- В противном случае, если любой операндunsigned
, другой должен быть преобразован вunsigned
.Примечание: в противном случае единственный оставшийся случай - это то, что оба операнда
int
]
Акции, на которые ссылаются в §4.5:
1 rvalue of type
char
,signed char
,unsigned char
,short int
, или жеunsigned short int
может быть преобразован в RVALUE типаint
еслиint
может представлять все значения типа источника; В противном случае источник RVALUE может быть преобразован в RVALUE типаunsigned int
.2
wchar_t
(3.9.1) или тип перечисления (7.2) может быть преобразован в RVALUE первого из следующих типов, которые могут представлять все значения его базового типа:int
,unsigned int
,long
, или жеunsigned long
.3 RVALUE для интегрального битового поля (9,6) может быть преобразовано в RVALUE типа
int
еслиint
может представлять все значения битового поля; в противном случае это может быть преобразовано вunsigned int
еслиunsigned int
может представлять все значения битового поля. Если битовое поле еще больше, к нему не применяется интегральная продвижение. Если битовое поле имеет перечисленный тип, он рассматривается как любое другое значение такого типа для целей продвижения.4
bool
может быть преобразован в RVALUE типаint
, сfalse
становится нулевым иtrue
становитсяone
.5 Эти конверсии называются интегральными акциями.
Отсюда, такие разделы, как "Мультипликативные операторы" или же "Аддитивные операторы"У всех есть фраза:"Обычные арифметические преобразования выполняются ...«Чтобы указать тип выражения.
Другими словами, когда вы делаете интегральную арифметику, тип определяется при вышеприведенных категориях. В вашем случае продвижение покрывается §4.5/1, а тип выражений int
.
Другие советы
Когда вы выполняете какую -либо арифметическую операцию на char
тип, результат, который он возвращает, имеет int
тип.
Посмотри это:
char c = 'A';
cout << sizeof(c) << endl;
cout << sizeof(+c) << endl;
cout << sizeof(-c) << endl;
cout << sizeof(c-c) << endl;
cout << sizeof(c+c) << endl;
Выход:
1
4
4
4
4
Демонстрация в iDeone: http://www.ideone.com/jntmm
Когда вы добавляете эти два символа друг с другом, они сначала повышаются до Int.
Результатом добавления является RValue, которое неявно продвигается в типе int, если это необходимо, и если INT может содержать полученное значение. Это верно на любой платформе, где sizeof (int)> sizeof (char). Но остерегайтесь того, что Чар может рассматриваться как подписанный Чар вашим компилятором.
Эти ссылки могут быть полезными - вики а также SecureCoding