C语言操作符详解(上):算术、移位与位运算实战

半杯拿铁
半杯拿铁
发布时间:2026-10-16 | 5人浏览过
原创

C语言中的操作符是构建程序逻辑的基础,掌握其内部机制能有效避免隐蔽Bug并优化性能。本文聚焦于算术、移位及位操作符三大类,详细拆解整数除法规则、左右移位的二进制处理逻辑,并利用异或特性演示无临时变量的变量交换技巧,帮助开发者建立扎实的底层运算思维。

1. 算术操作符:整除与取余的规则

算术操作符包括 +、-、*、/ 和 %。在日常使用中,最容易产生误解的是除法(/)和取余(%),尤其是它们对操作数类型的要求。

除法与取余的核心逻辑:

  • %(取模/取余):结果是被除数除以商后的余数。两侧必须为整数类型,不支持浮点数。
  • /(除法):若两侧均为整数,执行整数除法,小数部分被截断;只要有一侧为浮点数,则执行浮点除法。
#include<stdio.h>
int main()
{
	// 取余示例:10 % 3 = 1
	int ret1 = 10 % 3;
	
	// 整除示例:10 / 3 = 3 (截断小数)
	int ret2 = 10 / 3;
 
	printf("ret1=%d\nret2=%d\n", ret1, ret2);
 
	// 浮点除法示例:10.0 / 3 = 3.333...
	double ret = 10.0 / 3;
	printf("%lf\n", ret);
 
	return 0;
}

2. 移位操作符:左移与右移的二进制行为

移位操作符用于移动整数的二进制位。需要明确的是,移位操作仅适用于整数类型,且操作针对的是数据在内存中的补码形式进行位移,而输出显示时转换回原码。

第1步:理解左移(<<)

左移规则是将二进制位向左移动指定位数,右侧空出的位补0。这通常等同于乘以2的幂次。

#include<stdio.h>
int main()
{
	int a = 5;
	// a的二进制左移2位
	int b = a << 2;
 
	printf("b=%d\n", b); // 5 * 4 = 20
	printf("a=%d\n", a); // a本身保持不变
	return 0;
}

计算过程演示如下,直观展示位移前后的位变化:

第2步:理解右移(>>)的类型差异

右移分为算术右移和逻辑右移,具体行为取决于编译器的实现:

  • 算术右移:右边丢弃,左边补原来的符号位。如果是负数,左侧补1;正数补0。这是大多数现代编译器(如GCC、MSVC)的默认行为。
  • 逻辑右移:右边丢弃,左边统一补0。无论正负,高位均填0。

以下代码演示了5(正数)的右移行为:

#include<stdio.h>
int main()
{
	int a = 5;
	// 5的二进制右移2位
	int b = a >> 2;
	printf("%d\n", b); // 结果为1
    return 0;
}

3. 位操作符:与、或、异或的深度应用

位操作符直接对整数的二进制位进行操作。涉及的操作符有:&(按位与)、|(按位或)、^(按位异或)。

通过一段代码观察这三个操作符在处理不同数值时的表现:

#include<stdio.h>
int main()
{
    int a = 3;   // 二进制 ...0011
    int b = -5;  // 反码/补码计算后参与运算
    
    int x = a & b; // 按位与
    int y = a | b; // 按位或
    int z = a ^ b; // 按位异或
    
    printf("%d %d %d\n", x, y, z);
    return 0;
}

(1)按位与 &

规则:两位全为1则结果为1,否则为0。常用于特定位清零或提取某些位。

(2)按位或 |

规则:有一位为1则结果为1,全为0才为0。常用于置位。

(3)按位异或 ^ 的高级应用:无临时变量交换

异或的特性非常强大:任何数与自身异或结果为0,任何数与0异或结果为自身,即 A ^ A = 0,A ^ 0 = A。利用这一特性,我们可以不借助第三个临时变量来交换两个整数。

传统方法缺陷:

使用加减法交换看似可行:

int a = 3, b = 5;
a = a + b; // a=8, b=5
b = a - b; // b=3
a = a - b; // a=5

但此方法存在风险:当数值极大接近整型上限时,a+b 会导致溢出,产生错误结果。

异或交换法:

基于 x ^ y ^ y = x 的原理,步骤如下:

  1. a = a ^ b:将 a 保存为“a与b混合态”
  2. b = a ^ b:此时 a 为(a^b),再异或原b,得到 (a^b^b) = a。赋值给b,b现等于原a。
  3. a = a ^ b:此时 a 为(a^b),b已变为原a。故 (a^b)^a = b。赋值给a,a现等于原b。
#include<stdio.h>
int main()
{
	int a = 3, b = 5;
	printf("交换前:a=%d b=%d\n", a, b);
	
	a = a ^ b;
	b = a ^ b; // b 变为原 a
	a = a ^ b; // a 变为原 b
	
	printf("交换后:a=%d b=%d\n", a, b);
	return 0;
}

虽然异或法避免了溢出问题,但在现代CPU中,由于分支预测和流水线优化,读写寄存器交换速度极快,该方法的可读性较差,且在带有调试器或优化级别极高的场景下,编译器可能会将其还原。在实际工程开发中,若无特殊限制,直接使用临时变量交换仍是推荐做法。

4. 赋值操作符与复合赋值

除了基础的 =,C语言提供了丰富的复合赋值符,能将运算与赋值合并,既简洁又高效。例如 +=、-=、*=、/=、%=,以及位操作符对应的 &=、|=、^= 和移位对应的 <<=、>>=。

需要注意的是,+= 等表达式在语义上等价于 e1 = e1 op e2,但根据C标准,e1 只会被求值一次。这在处理数组或指针时尤为重要,可避免因多次求值导致的副作用。

连续赋值(如 a = b = c = 10)是从右向左执行的,但这属于一种不良的代码风格,应尽量拆分以保证清晰性。

以上就是C语言算术、移位及位操作符的详细解析与实战技巧,更多关于C语言操作符下篇的内容(如关系、逻辑、条件操作符)的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表