Яке призначення унарного оператора плюс (+) у C?


78

У C законно писати щось на зразок:

Однак, наскільки я можу зрозуміти, одинарний плюс ( +) у +4- це ні. Є це?


Не зовсім те ж саме, але пов'язані з : stackoverflow.com/questions/727516 / ...
jglouie

5
msdn.microsoft.com/en-us/library/s50et82s.aspx " Одинарний оператор плюс, що передує виразу в дужках, змушує групувати вкладені операції. Він використовується з виразами, що включають більше одного асоціативного або комутативного двійкового оператора. Операнд повинен мати арифметичний тип. Результат - це значення операнда. Цілісний операнд проходить інтегральне просування. Тип результату - це тип висунутого операнда. "
Тім С.

6
K&R каже, що його просто додали для симетрії в стандарт.
Аарон Йодайкен

2
@ Джеремі: є. Наприклад, це говорить, що +short(1)має тип int, а не short.
MSalters

1
@TimS .: "Одинарний оператор плюс, що стоїть перед виразом у дужках, змушує групувати вкладені операції " - О? Це дужки, а не те +, що змушує групувати.
Кіт Томпсон,

Відповіді:


34

Відповідно до стандарту C90 у 6.3.3.3:

Результатом оператора unary + є значення його операнда . Цілісне просування виконується на операнді. і результат має підвищений тип.

і

Операнд унарного оператора + або - повинен мати арифметичний тип .


1
Так +xце петля хіба що sizeof x < sizeof(int)?
zneak

31
Ці цитати зі стандарту показують, що одинарний + - це не просто відмова. Він дійсно виконує інтегральну рекламу операнда. І, можливо, що ще важливіше, це перетворює lvalue на rvalue.
Sander De Dycker

Ну, теоретично можливо, що sizeof(short) == sizeof(int)але a shortмає заповнення, і теоретично в такій системі відступ може знадобитися обнулити або розширити знак. Теоретично.
Дітріх Епп

Зверніть увагу, що коли в ньому сказано, що арифметичний тип він стосується як інтегральних типів, так і плаваючих типів, приклад Немо показує роботи, оскільки покажчики не входять до цієї класифікації. Цілісні типи та покажчики утворюють скалярні типи.
lccarrasco

Це взагалі не впливає на a floatчи a double, правда?
SS Anne

77

Ви можете використовувати це як своєрідне твердження, що вираз має арифметичний тип:

Це генерує помилку під час компіляції, якщо xобчислюється (скажімо) вказівником.

Це приблизно єдине практичне використання, яке я можу придумати.


7
Ви також можете передати значення перелічення цілому числу.
GManNickG

2
Чому ви не можете зробити те саме, наприклад, з (-(-(x)))?
Аарон Йодайкен

8
@luxun @zneak: Цікава ідея ... Давайте подивлюсь ... Добре, як щодо цього. Якщо intє 32-розрядним і, як xвиявляється, intдорівнює -2^31, то -xпереповнює підписане ціле число, яке є технічно невизначеною поведінкою. :-)
Немо

4
@zneak: Суть полягає в тому, щоб викликати помилку часу компіляції, якщо вираз має тип вказівника, але бути неприпустимим, якщо він має арифметичний тип. Ваша версія працює добре, за винятком арифметичних виразів, які випадково оцінюються INT_MIN. (Ну, теоретично, так чи інакше. На практиці це, мабуть, чудово працює на будь-якій реалістичній машині.) Однак, суворе читання стандарту говорить про те, що вони різні.
Немо

1
@zneak: Навіть якщо ви не використовуєте його в призначенні, просто оцінити , -xколи xце INT_MINтехнічно викликати невизначений поведінка, я вважаю.
Немо

35

Я знаю одне дуже зручне використання оператора unary plus в макросах. Припустимо, ви хочете зробити щось подібне

Якщо FOOне визначено, мова C вимагає, щоб у цьому випадку його замінили на 0. Але якщо це FOOбуло визначено з порожнім визначенням, вищевказана директива призведе до помилки. Натомість ви можете використовувати:

І тепер директива буде синтаксично правильною, незалежно від того FOO, визначена вона, визначена як порожня або визначена як ціле число.

Звичайно, чи це дасть бажану семантику - це зовсім окреме питання, але в деяких корисних випадках це буде.

Редагувати: Зверніть увагу, що ви навіть можете використовувати це, щоб розрізнити випадки, коли FOOвони визначаються як нуль, ніж визначені як порожні, як у:


1
Ви впевнені, що ці директиви препроцесора дійсно стосуються оператора unary +, як показано на C? У вашому другому прикладі, з порожнім FOO, вираз не буде дійсним C.
zneak

2
Дійсно. У будь-якому випадку, пара операторів - -(просторових!) Еквівалентна +, наскільки я можу зрозуміти, зробити +досить зайвою ... Ні, це неправильно, це не рівнозначно, коли операндом є INT_MIN... :-)
R. GitHub STOP HELPING ICE

2
Вибачте, що натрапив на таку стару відповідь, але хіба це не приклад двійкового плюсу, а не унарного плюса?
Aurora Vollvik

2
@AuroraVollvik: Це унарний плюс, якщо макрос виявляється визначеним, але з порожнім визначенням.
R .. GitHub СТОП ДОПОМОГАЙ ЛЕД

2
@UndefinedBehaviour: Унарний чи двійковий - залежить від того, як FOOце визначено.
R .. GitHub СТОП ДОПОМОГАЙ

17

Доволі багато. Це головним чином для повноти, і щоб зробити подібні конструкції виглядають трохи чистішими:


2
Це ніяк не чистіше, ніж альтернатива без одинарних +s.
ruohola

14

Не точно не-op

Унарний +оператор робить лише одне: застосовує цілочисельні підвищення . Оскільки вони все одно мали б місце, якби операнд був використаний у виразі, уявляємо, що одинарний +є в C просто для симетрії з одинарним -.

Важко побачити це в дії, оскільки рекламні акції застосовуються настільки загалом.

Я придумав таке:

який (на моєму Mac) друкує


1
Це корисно для друку chars на C ++ за допомогою std::cout.
SS Anne

13

Яке призначення одинарного оператора '+' в C?

Одинарний плюс було додано до C для симетрії з одинарним мінусом із Обґрунтування міжнародного стандарту —Мови програмування — C :

Одинарний плюс був прийнятий Комітетом C89 з декількох реалізацій, для симетрії з одинарним мінусом.

і це не операція, вона виконує цілочисельні акції на своєму операнді. Посилання з моєї відповіді на запитання Чи оператор Unary + робить перетворення типів?:

У проекті стандартного розділу C99 6.5.3.3 Унарні арифметичні оператори сказано:

Результатом унарного + оператора є значення його (розкрученого) операнда. Цілі числа підвищуються на операнді , а результат має підвищений тип.

Варто зазначити, що Анотований довідковий посібник C ++ ( ARM ) містить наступний коментар до унарних плюсів:

Одинарний плюс - це історичний випадок і взагалі марний.



13

Я знайшов дві речі, які робить одинарний +оператор

  • integer promotion
  • turning lvalue into rvalue

Приклад цілочисельного просування:

Типовий вихід (на 64-бітній платформі):

перетворення lvalue у приклад rvalue:


1
Нарешті. Потенційно корисна програма, яка повідомляє якийсь загальний код розміру аргументу після цілочисельного просування, якого може не бути sizeof(int). Я навіть не уявляю, коли буду цим користуватися. Але приємно все одно. NB: відредагована відповідь, щоб показати, що не все йде до 4.
Персіксті

1

Під "ні-op" ви маєте на увазі інструкцію по збірці?
Якщо так, то точно ні.

+4 - це просто 4 - компілятор не додаватиме подальших інструкцій.


2
Під терміном «noop» я мав на увазі «нічого не робити» - я сподіваюся, що компілятори не додають інструкції заради додавання інструкції.
zneak

3
Але +(char)4це не те саме, що (char)4.
DigitalRoss
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.