Выполняет ли оператор Unary + преобразование типов?

До сих пор я считал, что унарный оператор + бесполезен.

Но потом я наткнулся на следующий пример:

char ch;
short sh;
int i;

printf("%d %d %d",sizeof(ch),sizeof(sh),sizeof(i)); // output: 1 2 4

printf("%d %d %d",sizeof(+ch),sizeof(+sh),sizeof(i)); // output: 4 4 4

Означает ли это, что + выполняет здесь преобразование типов?

Потому что он ведет себя так же, как показано ниже

printf("%d %d %d",sizeof((int)ch),sizeof((int)sh),sizeof(i)); // output: 4 4 4

Это заставляет меня думать, что + выполняет преобразование типов.

Но потом попробую на double

double f;
printf("%d %d",sizeof(+f),sizeof((int)f),sizeof(f));  // output: 8 4 8

Это заставляет меня переосмыслить унарный оператор +.

Итак, мой второй вопрос: имеет ли унарный оператор + особый эффект в операторе sizeof?


person A.s. Bhullar    schedule 17.07.2014    source источник
comment
Что вас смущает в double? На ваш первый вопрос: да, + выполняет преобразование (целочисленные акции IIRC, поэтому float не получает double, но целые числа получают (без знака) int или что-то с более высоким рангом).   -  person mafso    schedule 17.07.2014


Ответы (4)


Унарный + выполняет целочисленное продвижение своего операнда, мы можем увидеть это, перейдя к черновому разделу стандарта C99 6.5.3.3 Унарные арифметические операторы, в котором говорится (выделено мной в будущем< /эм>):

Результатом унарного оператора + является значение его (расширенного) операнда. На операнде выполняется целочисленное повышение, и результат имеет повышенный тип.

и раздел 6.3.1 Арифметические операнды говорит:

Если int может представлять все значения исходного типа, значение преобразуется в int; в противном случае он преобразуется в беззнаковое целое число. Они называются целочисленными акциями.48) Все остальные типы целочисленных акций не меняются.

Обратите внимание, что все остальные типы не меняются целочисленными рекламными акциями, поэтому double остается double. Это также относится и к float, который не будет повышен до double.

Также обратите внимание, что использование %d для результата sizeof является неопределенным поведением, поскольку результатом является size_t. правильным спецификатором формата будет %zu.

person Shafik Yaghmour    schedule 17.07.2014
comment
спасибо за упоминание спецификатора формата %zu для sizeof, я никогда не слышал об этом раньше - person A.s. Bhullar; 17.07.2014
comment
использование %d для результата sizeof является неопределенным поведением в вопросе выше, оно дает ожидаемые результаты, когда мы получаем неожиданное поведение? - person Vinay Shukla; 28.05.2015
comment
@yanivx неопределенное поведение означает, что оно непредсказуемо, поэтому поведение, которое кажется разумным, возможно неопределенное поведение. Но мы можем найти множество случаев, таких как этот, когда компилятор позволяет себе делать некоторые неожиданные вещи. Существует множество UB, которые делают то, что вы ожидаете, но, возможно, не в будущем. - person Shafik Yaghmour; 28.05.2015

Когда меньшие типы участвуют в выражении с большими типами (например, char меньше, чем short, что в основном меньше, чем int, которое может быть меньше, чем long), типы превращаются в более крупные tyoes.

Так что да, когда вы используете унарный оператор +, вы получаете int, потому что int — это естественный целочисленный тип в C.

Что касается типа double, естественным типом с плавающей запятой для C является double, поэтому не происходит продвижения значений или переменных, которые уже имеют тип double.

Оператор sizeof не имеет к этому никакого отношения.

person Some programmer dude    schedule 17.07.2014
comment
Если вы собираетесь принять меры предосторожности, char в основном меньше, чем short. Процессор, который обрабатывает данные только одной ширины (например, DSP), может быть запрограммирован на компиляторе C, соответствующем стандарту, где char, short и int имеют одинаковую ширину (которая может быть 16-битной, 24-битной или 32-битной). например). - person Pascal Cuoq; 17.07.2014
comment
В первом абзаце вы говорите, что продвижение происходит, «когда меньшие типы участвуют… с большими типами», но операнд унарного + не связан с другими типами (большими или иными) в этом выражении. Так что второй абзац не следует из первого, хотя в остальном он правильный. - person Arkku; 17.07.2014
comment
@EliasVanOotegem Именно поэтому int8_t определяется только в том случае, если он существует, и почему у нас есть int_least8_t. Если бы int8_t всегда было определено, то int_least8_t не имело бы смысла, так как это могло бы быть только int8_t. stackoverflow.com/a/5254321/139746 - person Pascal Cuoq; 17.07.2014
comment
@PascalCuoq: ну, это меня заткнуло: D, хорошая мысль. Знак, что мне пора заканчивать - person Elias Van Ootegem; 17.07.2014
comment
@Joachim short преобразуется в int, потому что int является естественным типом для целых чисел, аналогично, если double является естественным типом для float, то преобразуется ли он в double? - person A.s. Bhullar; 17.07.2014
comment
@A.s.Bhullar float не будет повышен до double Я обновил свой ответ. Как говорится в моем ответе, целочисленные рекламные акции также не повлияют. - person Shafik Yaghmour; 17.07.2014

Унарный оператор + запускает «начальные» обычные арифметические преобразования, поэтому все целочисленные операнды, чей тип имеет более низкий ранг, чем ранг int и unsigned int, повышаются до int (или unsigned int, если тип int не охватывает все значения типа, продвигаемые в этой реализации).

person Grzegorz Szpetkowski    schedule 17.07.2014

Это не sizeof, это сам унарный +. Операнды унарного + подвергаются «обычным арифметическим преобразованиям». См., например, этот другой ответ с обычным добавлением.

person torek    schedule 17.07.2014