Linux-C成长之路(四)Linux C编程实战之路 运算符

Linux C编程实战之路

运算符

C语言提供了丰富的运算符,比如算术运算符、关系运算符、逻辑运算符等,下面的表格是C语言中所有的运算符一览:

算术运算符
运算符功能说明举例
+ 加法,或单目取正 a+b, +n
- 减法,或单目取负 a-b, -n
* 乘法 a * b
/ 除法 a / b
% 取模(求余) a % b
++ 自加1 a++,++b
-- 自减1 a--, --b

说明:取模 % 的左右两边的操作数必须都是整型。而自加和自减则分为前缀和后缀两种,请看下面的代码:

int a = 100, b;
int x = 200, y;

b = ++a; // 前缀,则a先进行自加1,然后再参与运算,因此此时 a 和 b 都等于101

x = y++; // 后缀,则 y 先参与运算,然后再自加1,因此此时 x等于200, 而y等于201

关系运算符
运算符功能说明举例
> 大于 a > b
>= 大于等于 a >= b
< 小于 a < b
<= 小于等于 a <= b
!= 不等于 a != b
== 等于 a == b


 

 

说明:由关系运算符组成的表达式称为关系表达式,每一个关系表达式的值都为布尔值,即非真即假。要注意的是,最后一个是 == 等于号,比如: a == b, 假如 a 跟 b 确实相等,那么此表达式的值为真,否则为假,等于号是用来判断左右两边是否相等的,不是数学意义上的“等于号”。

 

再来:

逻辑运算符
运算符功能说明举例
! 逻辑反 !(a == 100)
&& 逻辑与 a==100 && b==200
|| 逻辑或 a==100 || b==200


 

 

说明:

1, 逻辑反,就是取表达式的布尔值的相反值,例如 !(a==b) 假如 表达式 (a==b) 的值为真,那么 !(a==b) 的值就为假,反之亦然。

2,逻辑与, 就是当且仅当其两边的表达式都为真时,整个表达式才为真,例如 (a==100 && b==200) ,只有当 a==100 而且 b==200 同时为真时,整个表达式才为真。换句话说,在逻辑与表达式中,只要有一边的表达式为假,那么整个表达式必为假。

3,逻辑或, 就是当且仅当其两边的表达式都为假时,整个表达式才为假,例如 (a==100 && b==200) ,只有当 a==100 而且 b==200 同时为假时,整个表达式才为假。换句话说,在逻辑或表达式中,只要有一边的表达式为真,那么整个表达式必为真。

 

由上面的表述得知,有时候,第一个表达式的布尔值可以决定整个逻辑表达式的值,事实上,当逻辑与表达式的左边表达式的布尔值为假时,右边表达式将被忽略,同理,当逻辑或表达式的左边表达式的布尔值为真时,右边表达式也将被忽略。

 

位运算符
运算符功能说明举例
~ 位逻辑反 ~a
& 位逻辑与 a & b
| 位逻辑或 a | b
^ 位逻辑异或 a ^ b
     
<< 左移 a<<2
>> 右移 b>>2


位运算符中,前面三种跟逻辑运算符基本是一致的,只不过它们的操作对象不同,逻辑运算符操作对象是表达式,位运算符的操作对象是位,比如 ~a 结果就是对 a 的每一位求反, 而 a & b 或者 a | b 是对a 和 b 的每一位相应地进行与操作和或操作。位异或的逻辑是: 一样为0 不一样为 1,比如 a = 0000 1001 , b = 0000 1100 , 那么 a ^ b 的结果就是 0000 0101。

左移和右移则分别是对数位进行移动的操作,移出去的数位丢掉,空出来的补 0, 比如 原本 a 的二进制表示是 0000 1001, 如果执行 a = a<<2; 的话,那么结果是 a 的二进制表示就变成 (00)00 1001 00 最左边的两位被丢弃,最右边补上两个0, 右移是完全一样的道理,比如 b 的二进制表示是 0001 0110 ,如果执行 b = b >> 2; 的话,那么结果是 b 的二进制表示就变成 0000 0101(10) 。

有一个例外是,当被移动的数是一个有符号数,而且是一个负数的时候。 我们知道,负数在内存中的存储是以补码的方式存储的,即它们的最高位是 1, 此时如果被右移,为了保持其原有的正负号,系统会为其补 1 而不是补0. 比如有符号数 c 的二进制表示是 1000 1001, 那么执行 c = c >> 2; 的话,那么结果是 c 的二进制表示就变成 1110 10(01) 。

除了这几种运算符之外,C语言还包含以下几个特殊的运算符:

1, 赋值运算符 = 赋值运算符算是最常用最简单的运算符了,比如 int a; a = 100; 这里的 = 就是赋值运算符,代表将右边的值赋值给左边的变量。 注意不要跟逻辑等号==混淆了。

2,计算内存大小运算符 sizeof , 这个运算符用来计算一个变量或者一种数据类型在内存占用的字节数,比如 sizeof(int) 代表计算 int 类型所占的字节数,sizeof(a) 代表计算变量 a 所占的字节数。

3, 条件运算符 ? : 这个运算符比较特殊,它是唯一一个所谓的 三目 运算符,也就是说它有三个目标表达式,比如 (a>b) ? ( a ) : ( b ); 其中 (a>b) , ( a ) 和 ( b ) 分别是其三个目标表达式,它的逻辑很简单:首先问一下第一个表达式(即(a>b) ),如果它为真,那么就把第二个表达式 ( a ) 的值作为 整个表达式的值,否则就将 第三个表达式(即( b ) 的值作为 整个表达式的值。

4, 逗号运算符 , 逗号其实是用来分割各个其他的表达式的,所以它的优先级最低,比如: int a = (x = 100, y = 200, z = x + y, z + 1); 对于由逗号连起来的表达式,我们记住三点即可: 第一,逗号的优先级最低,全部算完了你再来考虑它。 第二,计算次序从左到右,先算 x = 100, y = 200, 再来 z = x + y, 再到 z +1 。 第三,整个逗号表达式的值取决于最右边的表达式的值,也就是最后a 的值为 z + 1。

5,复合赋值运算符: += -= *= /= %= >>= <<= &= ^= |=

这些操作符的用法是: a += b 相等于 a = a + b 。 a -= (x * y) 相当于 a = a - (x*y) 以此类推。 在可以使用复合赋值运算符的情形下,推荐尽量使用,比如使用 a += b 比使用

a = a + b 要好,因为可以使得程序少一条机器指令。

另外讲几个常见的关键字:

1, return

这个运算符在函数当中使用,请看下面的解释:

int func(void)
{
    ...
    ...
    return 100; // 在普通函数中使用,代表返回到调用者处
}

int main(void)
{
    ...
    ...
    return 0;  // 在main函数中使用,代笔退出当前进程
}

由以上示例可知,return 有两个作用,在普通函数中使用和在主函数中使用是不同的。 在主函数中的返回值,将会被传递给其父进程,在非多进程程序里面,这个值无意义。 在多进程程序中,main函数的返回值一般情况下是这么约定的: 返回0 代表正常,返回非0 代表异常。

另外,在LINUX 下C编程,使用的是GNU 扩展语法,gcc还支持以下关键字:

2, typeof

取得变量的类型。比如

int a;
typeof(a) b;  // 等价于 int b;

typeof 在复杂宏中用得比较多。比如典型在求最大值的“标准宏”如下:

#define MAX(a, b) ({ \
            typeof(a) _a = a; \
            typeof(b) _b = b; \
            (void)( &_a == &_b); \ 
            _a > _b ? _a : _b; \
                              )}

这个宏之所以这么写,而不是直接写第 5 行,是因为要避免宏参数如果出现 a++ 这样的自加自减符的时候的副作用,因为如果直接写 (a>b) ? (a) : (b) 的话可能会将自加自减符运算两遍,而用typeof 来分别取得 a 和 b 的类型,再定义另两个变量来替换 a 和 b ,就能避免这种副作用。看下面的例子:

#define MAX_BAD(a, b) ((a>b)?(a):(b))

int a = 100, b = 1, c;
c = MAX_BAD(a++, b); // 按照调用者的思路,运算之后c 应该等于100, a 应该等于101,但是情况并非如此,因为宏替换将使得 a++ 出现两次

上面的例子中,如果我们使用的是 MAX() 而不是 MAX_BAD() 情况就会好转。

另外,MAX() 中的 语句: (void)(&_a == &_b); 是用来判断 _a 和 _b 的类型是否一致的, 假如它们类型不一致,那么它们的指针也必然不一致,不同类型的指针相比较,编译器就会为我们发出警告。 这就是表达式 (&_a == &_b)的作用,而它前面的 (void) 是用来避免编译器因为表达式 (&_a == &_b) 而发出" no effect " 的警告用的。(因为编译器会认为你写了一个逻辑等表达式但是没有使用它,我们用(void)来骗过编译器使其不要发出" no effect " 的警告)


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值