括号在c语言中的优先级,c ++ - 除了运算符优先级之外,什么时候额外的括号有效?...

TL; DR

额外的括号在以下上下文中更改了C ++程序的含义:

防止依赖于参数的名称查找

在列表上下文中启用逗号运算符

困惑解决烦恼的解析

在(min)(a, b)表达式中推导出参考

防止预处理器宏错误

防止依赖于参数的名称查找

如标准的附录A中所详述,TIMES(1 + 2, 2 + 1)形式的(min)(a, b)是(A),但不是(B),因此不是e。这意味着在形式(fun)(arg)的函数调用中防止了与参数相关的名称查找。 传统形式fun(arg)。

3.4.2依赖于参数的名称查找[basic.lookup.argdep]

1当函数调用(5.2.2)中的postfix-expression为。时   unqualified-id,通常不考虑的其他名称空间   可以搜索非限定查找(3.4.1),并在这些名称空间中,   命名空间范围的朋友函数或函数模板声明   (11.3)可能无法看到。 这些修改   搜索取决于参数的类型(以及模板模板)   参数,模板参数的命名空间)。 [例如:

namespace N {

struct S { };

void f(S);

}

void g() {

N::S s;

f(s); // OK: calls N::f

(f)(s); // error: N::f not considered; parentheses

// prevent argument-dependent lookup

}

- 末端的例子]

在列表上下文中启用逗号运算符

逗号运算符在大多数类似列表的上下文(函数和模板参数,初始化列表等)中具有特殊含义。 在这样的上下文中,窗体(min)(a, b)的括号可以使逗号运算符与逗号运算符不适用的常规形式TIMES(1 + 2, 2 + 1)相比较。

5.18逗号运算符[expr.comma]

2在逗号被赋予特殊含义的上下文中,[例如:in   函数参数列表(5.2.2)和初始值列表   (8.5) - 例子]如第5条所述的逗号运算符可以   仅出现在括号中。 [例如:

f(a, (t=3, t+2), c);

有三个参数,第二个参数的值为5. -end示例  ]

令人烦恼的解析模糊解析

向后兼容C及其神秘的函数声明语法可能导致令人惊讶的解析歧义,称为烦恼的解析。 从本质上讲,任何可以解析为声明的内容都将被解析为一个,即使竞争解析也适用。

6.8歧义解决[stmt.ambig]

1涉及表达式语句的语法含糊不清   和声明:具有函数样式的表达式语句   显式类型转换(5.2.3),因为它最左边的子表达式可以   与第一个声明者开始的声明无法区分   (a。在这些情况下,声明是声明。

8.2歧义解决[dcl.ambig.res]

1函数式之间相似性产生的歧义   在6.8中提到的演员和声明也可以在上下文中出现   声明。 在这种情况下,选择是在一个函数之间   声明与参数周围的一组冗余括号   具有函数样式转换的名称和对象声明  初始化。 正如6.8中提到的含糊不清一样   解决方案是考虑任何可能是a的构造   声明声明。 [注意:声明可以明确   由非函数式转换消除歧义,由=表示   初始化或删除周围的冗余括号   参数名称。 - 尾注] [示例:

struct S {

S(int);

};

void foo(double a) {

S w(int(a)); // function declaration

S x(int()); // function declaration

S y((int)a); // object declaration

S z = int(a); // object declaration

}

- 末端的例子]

一个着名的例子是最令人兴奋的解析,这是Scott Meyers在他的Effective STL书的第6项中推广的名称:

ifstream dataFile("ints.dat");

list data(istream_iterator(dataFile), // warning! this doesn't do

istream_iterator()); // what you think it does

这声明了一个函数(min)(a, b),其返回类型为TIMES(1 + 2, 2 + 1)。函数数据有两个参数:

第一个参数名为(min)(a, b).它的类型是TIMES(1 + 2, 2 + 1)。(A)左右的括号是多余的,被忽略了。

第二个参数没有名称。 它的类型是函数获取的指针没有,返回(min)(a, b)。

在第一个函数参数周围放置额外的括号(第二个参数周围的括号是非法的)将解决歧义

list data((istream_iterator(dataFile)), // note new parens

istream_iterator()); // around first argument

// to list's constructor

C ++ 11具有大括号初始化器语法,允许在许多上下文中支持这样的解析问题。

在(min)(a, b)表达式中推导出参考性

与(min)(a, b)类型推导相比,TIMES(1 + 2, 2 + 1)允许推导出参考(左值和右值参考)。 规则区分(A)和(B)表达式:

7.1.6.2简单类型说明符[dcl.type.simple]

4对于表达式(min)(a, b),(min)(a, b)表示的类型定义为  如下:

- 如果(min)(a, b)是未表示的id-expression或   unarenthesized类成员访问(5.2.5),TIMES(1 + 2, 2 + 1)是类型   由(A)指定的实体。如果没有这样的实体,或者如果(B)命名为   一组重载函数,程序格式不正确;

- 除此以外,   如果(min)(a, b)是xvalue,则TIMES(1 + 2, 2 + 1)是(A),其中(B)是e的类型;

-    否则,如果(min)(a, b)是左值,TIMES(1 + 2, 2 + 1)是(A),其中(B)是类型   e;

- 否则,(min)(a, b)是TIMES(1 + 2, 2 + 1)的类型。

的操作数   decltype说明符是未评估的操作数(第5条)。 [例如:

const int&& foo();

int i;

struct A { double x; };

const A* a = new A();

decltype(foo()) x1 = 0; // type is const int&&

decltype(i) x2; // type is int

decltype(a->x) x3; // type is double

decltype((a->x)) x4 = x3; // type is const double&

- 末端示例] [注:确定类型涉及的规则   (min)(a, b)在7.1.6.4中规定。 - 尾注]

对于初始化表达式的RHS中的额外括号,(min)(a, b)的规则具有类似的含义。 以下是C ++ FAQ和此相关问答的示例

decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str; } //A

decltype(auto) look_up_a_string_2() { auto str = lookup1(); return(str); } //B

第一个返回(min)(a, b),第二个返回TIMES(1 + 2, 2 + 1),这是对局部变量(A)的引用。

防止预处理器宏相关错误

在与C ++语言交互时,预处理器宏有许多细微之处,其中最常见的是下面列出的

在宏定义(min)(a, b)内的宏参数周围使用括号,以避免不必要的运算符优先级(例如,在TIMES(1 + 2, 2 + 1)中产生9但在没有括号的情况下产生6而在(A)和(B)附近

在内部使用逗号的宏参数周围使用括号:(min)(a, b)否则将无法编译

在函数周围使用括号来防止包含头文件中的宏扩展:(min)(a, b)(同时禁用ADL的不必要的副作用)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言的运算符有多种,不同的运算符具有不同的优先级。如果不了解运算符优先级,程序的运算结果可能会出现错误。下面是C语言运算符优先级顺序表: 1. 括号 () 括号用于改变优先级顺序,最高优先级。 2. 单目运算符 +、-、!、~、++、-- 单目运算符作用于一元操作数,并且优先级较高。 3. 乘除模运算符 *、/、% 乘、除、模运算符具有相同的优先级,高于加、减运算符。 4. 加减运算符 +、- 低于乘、除、模运算符,但高于比较运算符。 5. 移位运算符<<、>> 比较位运算符优先级高,低于乘、除、模、加、减运算符。 6. 关系运算符 <、<=、>、>= 关系运算符的优先级低于逻辑运算符。 7. 相等运算符 ==、!= 相等运算符的优先级低于关系运算符。 8. 按位与运算符 & 按位与运算符的优先级低于相等运算符。 9. 按位异或运算符 ^ 按位异或运算符的优先级低于按位与运算符。 10. 按位或运算符 | 按位或运算符的优先级低于按位异或运算符。 11. 逻辑与运算符 && 逻辑与运算符的优先级低于按位或运算符。 12. 逻辑或运算符 || 逻辑或运算符的优先级低于逻辑与运算符。 13. 条件运算符 ? : 条件运算符是C语言唯一的三元运算符,优先级低于逻辑或运算符。 14. 赋值运算符 =、+=、-=、/=、%=、&=、^=、|=、<<=、>>= 赋值运算符优先级最低。 通过掌握C语言运算符优先级顺序表,我们可以正确理解和使用不同的运算符,从而避免程序的错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值