C 语言非常灵活且富有表现力;这些是它成功并能够被“更好”的语言取代的一些原因。其灵活性的一个例子是可以以多种功能等效的方式编写表达式。这使得编码风格能够适应个人需求。但是,有一个问题:有时,表面上等效的代码有细微的差别。这可以在最简单的代码中发生,我们将在本文中探讨一些可能性。
C 提供几种不同的方法来做某事是很常见的,所有这些方法都是完全等价的。例如,假设x是一个普通的int变量,以下每个语句都将执行完全相同的工作:
x = x + 1; x += 1; x++; ++x;
在每种情况下,都会将1添加到x。唯一可能的区别是,功能较弱的编译器可能会为最后两个选项生成稍微更好的代码(这暗示着获得更好的编译器是值得的)。
以这种方式使用的两种形式的++运算符产生相同的结果。但是,如果使用表达式的值,则前置增量和后置增量是不同的,因此:
y = x++; // y 在增量之前具有 x 的值 y = ++x; // y 在增量后具有 x 的值
有趣的是,后增量稍微“昂贵”一些,因为需要分配存储以保持x的旧值。但是,编译器可能会将其优化掉。如果在不使用表达式值时分配存储,那么肯定需要新的编译器!
如果x不是int,而是指向int的指针,则加1将具有加4的效果(在 32 位机器上)。如果这是一个很大的惊喜,那么重新学习指针算法是必要的。
然而,有时看起来等价的结构会有非常细微的差异……
在任何编程语言中,您可以做的最简单的事情可能就是为变量赋值。因此,在 C 语言中,我们可以这样写:
阿尔法 = 99; 贝塔 = 99; 伽玛 = 99;
当然,这可能会写得更紧凑,如下所示:
阿尔法 = 贝塔 = 伽马 = 99;
这些是 100% 等效的。还是他们?
大多数情况下,这两种结构是完全等价的,但是(至少)有四种情况选择其中一种可能会有所不同:
首先,也是最平淡无奇的,每个变量都是独立的,也许一个注释说明为什么它被设置为这个值可能是合适的。
其次,编写可维护的代码总是好的。也许,在将来的某个时候,可能需要更改代码,以便所有三个变量都不会设置为相同的值。第一种格式更容易修改。
第三个原因与不合标准的编译器有关,它可能会为第一个构造生成如下代码:
mov r0, #99 移动阿尔法,r0 mov r0, #99 mov beta, r0 mov r0, #99 mov 伽马, r0
第二个构造暗示r0只需要加载一次。同样,更好的编译器不需要提示。
最后是执行顺序的问题。在第一个构造中,很明显 alpha 将首先分配,而 gamma 最后分配。编译器将这样解释第二个构造:
阿尔法 = (贝塔 = (伽马 = 99));
这意味着分配顺序是颠倒的。但这有关系吗?大多数时候,它没有。但如果这些是设备寄存器,而不是普通变量,它可能会产生很大的不同。硬件需要以精确的顺序加载设置值是很常见的。
所以,我想说应该避免在一个语句结构中进行多个赋值。
总体而言,尽管 C 是一种小型语言,但可以说它可以通过提供更少的做事方式来变得更小。结果可能是更清晰、更易于维护的代码。
审核编辑:郭婷
-
代码
+关注
关注
30文章
4976浏览量
74369 -
编译器
+关注
关注
1文章
1672浏览量
51903 -
C代码
+关注
关注
1文章
90浏览量
15227
发布评论请先 登录
80后硬件人 I 青春藏在焊盘里,热爱写在代码中
深度解析SPL阶段A/B分区启动:spl_ab.c代码全拆解
c语言中的代码优化
FLASH中的代码是如何得到运行的呢
求助,关于C代码中的printf打印的疑问求解
请问cypd3125在 ( EZ-PD™ CCGx Host SDK) 中的流程代码如何从main.c到所有.c运行里面有文件吗?
嵌入式系统中,FLASH 中的程序代码必须搬到 RAM 中运行吗?
Perforce QAC产品简介:面向C/C++的静态代码分析工具(已通过SO 26262认证)
深入理解C语言:函数—编程中的“积木块”艺术
用CubeMX生成代码时会将main.c文件中的汉字变成乱码,怎么解决?
在OpenVINO™ C++代码中启用 AddressSanitizer 时的内存泄漏怎么解决?
深入理解C语言:C语言循环控制
C代码中的惊喜
评论