Имеют ли унарные операторы более высокий приоритет, чем выражение приведения? - PullRequest
1 голос
/ 03 августа 2020

Я изучал C через известную книгу c premier плюс 6-е издание , и у меня есть некоторая путаница в отношении приоритета унарных операторов и выражение приведения.

Я получаю PDF-версию книги здесь , а расположение таблицы, упомянутой ниже в этой книге, - B: Reference Section Section II: C Operators--Table RS.II.1.

Согласно book, выражение приведения, похоже, имеет более низкий приоритет по сравнению с унарными операторами. Итак, я провел простой тест, и почему-то оказалось, что они имеют одинаковый приоритет. Вот тестовый файл ниже:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    /*we take advantage of the truncation when casting int to char(only remains the lower 8 bit of the int), if the cast executes first, the value is 0 so the final output is 1. Conversely, we get 0 as the final result.*/
    int test = 512;
    printf("test1-1 is %d\n",!(char)test); /*test1-1 is 1*/
    printf("test1-2 is %d\n",(char)!test); /*test1-2 is 0*/

    getchar();
    return 0;
}

В этом тестовом файле я выбрал унарный оператор ! в качестве представления. Конечно, есть и другие унарные операторы, но у всех есть веские причины не участвовать в этом тесте:

  • ++, - и &: они могут использовать только lvalue в качестве операнда, это не то, что выражение приведения может организовать для
  • -, + и ~: мы можем объявить переменную long long int и преобразовать ее как int, возможно, усечение может нам что-то сказать. К сожалению, мы ничего не можем найти из этого, сделайте базовую c математику, вы узнаете, выполняется ли сначала унарный оператор или сначала выполняется приведение, это все равно не меняет вывод.
  • другие: просто не имеют для меня смысла

Вот мои настройки среды: g cc версия: gcc (tdm-1) 5.1.0 ОС: windows7

Я добавил параметры команды, например -std=c90 , -std=c99, -std=c11, все они производят тот же результат, что и комментарий в тестовом файле. Это странно, поэтому я обращаюсь за помощью к стандартному документу C11, и относительная информация здесь . Итак, вот информация:

1. Синтаксис определяет приоритет операторов при вычислении выражения, который совпадает с порядком основных подпунктов этого подпункта, сначала высший приоритет.

2. Исключениями являются выражения приведения (6.5.4) в качестве операндов унарных операторов и ...

Это многое объясняет, но поведение такое же, как если бы они разделяли такой же приоритет. Так почему бы не собрать их вместе и не ввести в заблуждение? Просто потому, что выражение приведения не принадлежит к унарным операторам, и чтобы сохранить чистоту до c, поэтому мы должны дать выражению приведения другой приоритет? Это немного ОКР.

1 Ответ

2 голосов
/ 03 августа 2020

Давайте сосредоточимся на операторах, которые вы анализируете в своем тесте. Оператор логического не ! и оператор приведения (type) do имеют одинаковый приоритет.

Как вы можете видеть в этой таблице , они оба имеют приоритет # 2 .
То, что вам нужно, чтобы понять, что происходит, также учитывает ассоциативность . Ассоциативность представляет собой порядок, в котором будут оцениваться операторы с одинаковым приоритетом.
Операторы, о которых мы говорим, имеют Справа налево ассоциативность.

Я скопирую ваш тест для ясности:

int main(void)
{
    /*we take advantage of the truncation when casting int to char(only remains the lower 8 bit of the int), if the cast executes first, the value is 0 so the final output is 1. Conversely, we get 0 as the final result.*/
    int test = 512;
    printf("test1-1 is %d\n",!(char)test); /*test1-1 is 1*/
    printf("test1-2 is %d\n",(char)!test); /*test1-2 is 0*/

    getchar();
    return 0;
}
  1. В !(char)test ассоциативность справа налево означает, что преобразование выполняется первым. Это приводит к тому, что значение "адаптируется" к размеру char, в результате получается значение 0.

    Затем вы применяете логическое отрицание, в результате чего получается значение 1

  2. В (char)!test ассоциативность справа налево означает, что сначала выполняется логическое отрицание. Это приводит к значению !512, что приводит к значению 0.

    Затем вы применяете приведение, которое снова приводит к значению 0

По этим причинам , вы действительно получите ожидаемые результаты.

...