Всегда ли скобки считаются вызовом функции?

Я просматривал эту страницу: https://en.cppreference.com/w/c/language/operator_precedence

Мое внимание привлекло то, что описание Только оператора скобок было вызов функции. Означает ли это, что выражение x = a * (b+c)-(d*e) имеет два вызова функций?

Я искал в C грамматика и Стандарт C, но не смог найти ничего, что либо поддерживало бы, либо противоречило этому.

Нет, круглые скобки используются точно так же, чтобы задать приоритет оператора, точно так же, как это делается в простой математике.

Thomas Jager 22.05.2019 15:49
parenthesis operator.. интересно, а где вы это нашли?
Sourav Ghosh 22.05.2019 15:51

Это означает, что когда () используется для вызова функции (независимо от того, как еще он может использоваться), он имеет приоритет 1. Чуть ниже вы можете увидеть, например, (type) Type cast с приоритетом 2.

Blaze 22.05.2019 15:52

Похоже, вы пропустили некоторые главы из стандарта. Бывший. 6.5.1p5

KamilCuk 22.05.2019 15:52

Попробуйте поискать '(' на странице грамматики C. Они используются во многих других местах, а не только в постфиксных выражениях (=> вызовы функций).

PSkocik 22.05.2019 15:52
x = a * (b+c)-(d*e) — это выражение, а не утверждение. Здесь ( не оператор. Термин «оператор скобок» относится к тому, где () используется в качестве оператора. Точно так же в int *p = 0;* и = не являются операторами, хотя одни и те же символы используются для операторов в разных контекстах.
M.M 22.05.2019 15:54

@KamilCuk Итак, вы говорите, что это первичное выражение, а () НЕ является оператором?

klutt 22.05.2019 15:55
порт70.net/~nsz/c/c11/n1570.html#6.5.1
StoryTeller - Unslander Monica 22.05.2019 15:55

@SouravGhosh На странице, на которую я дал ссылку.

klutt 22.05.2019 15:56

@ Броман Перечитай это. Это оператор вызова функции, а не оператор скобок.

Sourav Ghosh 22.05.2019 15:58

@SouravGhosh Значит, обычная скобка не является оператором?

klutt 22.05.2019 15:59

@ Броман Нет, это не так.

Sourav Ghosh 22.05.2019 15:59

Корень проблемы в том, что связанная таблица приоритетов полна и полна мусора. В этом так много неправильного, что мы должны обратиться к cppreference с просьбой закрыть эту страницу. Его нельзя спасти.

Lundin 22.05.2019 16:03

@Lundin Звучит как хорошая основа для хорошего ответа. Однажды я дал ответ на основе разглагольствования на tutorialspoint.

klutt 22.05.2019 16:07

Кажется, что (одно из) моих недоразумений состоит в том, чтобы предположить, что обычные круглые скобки считаются операторами, но ни один ответ ниже не касается этой конкретной проблемы.

klutt 22.05.2019 16:08

@ Лундин Правда? Я считаю, что это хороший справочник, который поможет среднему читателю понять приоритет операторов без необходимости вникать в стандартную грамматику языка.

dbush 22.05.2019 16:09

@Lundin Вот оно: stackoverflow.com/a/55731680/6699433

klutt 22.05.2019 16:13

Однажды я начал какой-то проект, чтобы предоставить надежную таблицу приоритетов для SO, но он застрял. Мое главное возражение против cppreference — неправильные имена почти для каждого оператора.

Lundin 22.05.2019 16:24
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
4
18
225
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

№ идентификатор( вызывает идентификатор как функцию. Если сразу после круглых скобок нет идентификатора или полного выражения, вызов не выполняется.

Когда я впервые изучал c, у меня была противоположная проблема. Я не мог понять, почему clrscr; не очистил экран. (Это выражение, которое возвращает указатель на clrscr, но ничего с ним не делает).

На самом деле у вас могут быть выражения типа указатель на функцию, и эти выражения могут быть вызваны с помощью (), и грамматика между ними полностью недвусмысленна. Итак, clrscr(); — это вызов функции, как и (clrscr)(). Достигнув указателей на функции, мы также можем сделать resolve_function()(). Операция всегда ( сразу после выражения, а не после оператора. Если она после оператора, она должна быть группирующей скобкой.

Грамматика для вызова функции: «постфиксное выражение(список-выражений-аргументов)», где список-выражений-аргументов является необязательным. постфиксное выражение не обязательно должен быть идентификатором. Это может быть указатель на функцию, даже вызов функции, возвращающий указатель на функцию.

Eric Postpischil 22.05.2019 16:23

@EricPostpischil: Вы правы. Я предположил уровень ОП и написал соответственно.

Joshua 22.05.2019 17:09

Вы можете отредактировать свой ответ. Я часто сталкиваюсь с проблемой обращения к новичку, а также хочу сказать всю правду, и есть разные подходы. Можно написать, что «идентификатор(аргументы)» — это всегда вызов функции, а скобки без выражения непосредственно перед ними — это выражение в скобках или приведение (а не вызов функции), а потом можно добавить, что «постфиксное выражение(аргументы)» также является вызовом функции, который используется с указателями на функции, а также с именами функций.

Eric Postpischil 22.05.2019 23:56

Также было бы неплохо упомянуть, что грамматика C, которая является формальным описанием структуры исходного кода C, всегда позволяет отличить их друг от друга.

Eric Postpischil 23.05.2019 00:00
Ответ принят как подходящий

Скобки можно использовать как оператор вызова функции, но они используются не только для этого. Они также используются для группировки выражений, как в вашем примере.

То, что вы ищете, находится в разделе 6.5.1 Стандарт C, в котором обсуждаются первичные выражения:

Syntax

1

primary-expression:
  identifier
  constant
  string-literal
  ( expression )
  generic-selection

...

5A parenthesized expression is a primary expression. Its type and value are identical to those of the unparenthesized expression. It is an lvalue, a function designator, or a void expression if the unparenthesized expression is, respectively, an lvalue, a function designator, or a void expression.

Как указано выше, круглые скобки можно использовать для группировки выражений.

Использование в качестве оператора вызова функции подробно описано в разделе 6.5.2 о постфиксных выражениях:

postfix-expression:
  ...
  postfix-expression(argument-expression-list opt)
  ...

Итак, в вашем выражении:

x = a * (b+c)-(d*e)

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

Кроме того, помимо группировки выражений, круглые скобки используются и в других частях грамматики языка. Раздел 6.8.4, касающийся операторов выбора, использует круглые скобки в грамматике операторов if и switch:

  • if (expression) statement
  • if (expression) statement else statement
  • switch (expression) statement

А в разделе 6.8.5, касающемся операторов итерации, также используются круглые скобки в грамматике операторов while и for.

  • while (expression) statement
  • do statement while (expression);
  • for (expressionopt; expressionopt; expressionopt) statement
  • for (declarationexpressionopt; expressionopt ) statement

Не могли бы вы добавить что-нибудь о том, что круглые скобки не всегда считаются оператором. Это то, что кажется (одним из) моих недоразумений.

klutt 22.05.2019 16:36

Вызов функции представляет собой постфиксное выражение.

Вот в этих выражениях

x = a * (b+c)-(d*e);

подвыражения (b+c) и (d*e) являются первичными выражениями. Вы можете заключить любое выражение в круглые скобки, и вы получите первичное выражение.

Например, вы можете даже переписать оператор выражения следующим образом.

( x = ( ( ( a ) * (b+c) )-(d*e) ) );

В этом операторе выражения есть следующие первичные выражения

( a )
(b+c)
(d*e)
( ( a ) * (b+c) )
( ( ( a ) * (b+c) )-(d*e) )
( x = ( ( ( a ) * (b+c) )-(d*e) ) )

Вот несколько примеров постфиксных выражений

( *p )() // a function call

a[n] // using the subscript operator

x++; // using the postfix increment operator

Определение вызова функции

postfix-expression:
    primary-expression
    postfix-expression ( argument-expression-listopt )

Из стандарта C (6.5.2.2 Вызовы функций)

1 The expression that denotes the called function92) shall have type pointer to function returning void or returning a complete object type other than an array type.

Вот несколько примеров странных вызовов функций. :)

#include <stdio.h>

void f( void )
{
    printf( "Hello " );
}

void g( void )
{
    puts( "Broman" );
}    

int main( void )
{
    void ( *funcs[] )( void ) = { f, g };

    void ( **p_func )( void ) = funcs;

    ( *p_func++ )();
    p_func[0]();
}

Вывод программы

Hello Broman

Учтите, что в этих звонках

    ( *p_func++ )();
    p_func[0]();

выражение ( *p_func++ ) является первичным выражением, а выражение p_func[0] является постфиксным выражением (см. частичное определение постфиксного выражения выше)

(*p)() и (*p) оба являются постфиксное выражение, что может немного сбить с толку новичка. Говоря о вызовах функций, термин «постфиксное выражение» обычно относится к выражению перед оператором вызова функции.
M.M 22.05.2019 16:15

Другие вопросы по теме