c - 一元运算符的优先级是否高于强制转换表达式?
问题描述
我一直在通过着名的书籍c Premier plus 6th edition学习 C ,我对一元运算符的优先级和强制转换表达式有些困惑。
我在这里得到了这本书的 pdf 版本,本书下面提到的表格的位置是B: Reference Section Section II: C Operators--Table RS.II.1
.
根据本书的表格,与一元运算符相比,强制转换表达式的优先级似乎较低。所以我对它进行了一个简单的测试,不知何故,它们似乎具有相同的优先级。下面是测试文件:
#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;
}
在这个测试文件中,我选择一元运算符! 作为代表。当然,还有其他一元运算符,但它们都有充分的理由不参与此测试:
- ++ , -- 和 &:它们只能使用左值作为操作数,这不是强制转换表达式可以安排的
- -、+ 和 ~:我们可以声明一个 long long int 变量并将其转换为 int,也许截断可以告诉我们一些事情。不幸的是,我们无法从中找到任何东西,做一些基本的数学运算,你会发现是一元运算符先执行还是强制转换先执行,无论如何它不会改变输出。
- 其他人:对我来说毫无意义
这是我的环境设置:gcc 版本: gcc (tdm-1) 5.1.0
操作系统:windows7
我添加了命令选项,如-std=c90
, -std=c99
, -std=c11
,它们都产生与测试文件中的注释完全相同的输出。这很奇怪,所以我求助于 C11 标准文档,相关信息在这里。所以这里的信息:
1.语法规定表达式求值中运算符的优先级,与本小节主要小节的顺序相同,最高优先级在前。
2.例外是强制转换表达式(6.5.4)作为一元运算符的操作数和......
这解释了很多,但行为是相同的,就好像它们共享相同的优先级一样。那么为什么不把它们放在一起以避免误导呢?只是因为强制转换表达式不属于一元运算符,并且为了保持 toc 的干净所以我们必须给强制转换表达式不同的优先级?这有点强迫症。
解决方案
让我们关注您在测试中分析的运算符。逻辑非!
运算符和强制转换运算符(type)
确实具有相同的优先级。
正如您在此表中看到的,它们都有优先级#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;
}
在
!(char)test
中,从右到左的关联性意味着首先执行强制转换。这导致值“适应”char
大小,从而产生 value0
。然后应用逻辑否定,得到值
1
在
(char)!test
中,从右到左的结合性意味着首先执行逻辑否定。这导致价值!512
,产生价值0
。然后你应用强制转换,再次产生值
0
由于这些原因,您实际上得到了预期的结果。
推荐阅读
- python - 使用 CSV 的第二列按升序排序?
- netty - Netty ctx.executor().scheduleAtFixedRate 任务在通道关闭时也可以工作
- android-layout - Android多屏指南
- java - 我如何发送带有 groovy 错误的电子邮件(com.sun.mail.smtp.SMTPSendFailedException: 530-5.5.1 Authentication Required。了解更多信息)
- azure-ad-b2c - 根据扩展属性阻止/拒绝用户登录
- javascript - 在按钮单击时附加 JSON 值
- debian - 在 Debian 之外构建轮子
- javascript - JS 粒子注入 param :id (在本地显示,不在 Heroku 生产中)
- tsql - TSQL:为表 IDENTITY 列设置起始编号
- python - Keras 函数式 API 多输入 LSTM