北理工考研885知识点拾遗01:C语言的一些细节 木灵的炼金工作室

1. C语言常量词法

  • 八进制数: $0\ digit8*$,对应的标准输出为”%o”
  • 十六进制数:$0x\ digit16*$或$0X\ digit16$,对应的标准输出为”%x”或”%X”,大小写分别决定输出结果的大小写
  • 二进制数:$0b\ digit2$或$0B\ digit2$ 高版本编译器
  • 指数常量中,基数部分可以是任意浮点数或整数,但指数部分必须是整数。E不区分大小写。

2. C运行时对析取范式或合取范式的优化

如一个由逻辑判断符号结合起来的逻辑范式的前一部分可以直接确定范式的值,那么后边的部分不会被计算。

例:执行下述语句后,i和j的值是?

int i = 1, j = 2;
int res = (j = !j && i++);

首先,运行时进行到语句j = !j,发现返回0且运算符是合取,程序不再执行i++。故结果j = 0, i = 1

同理,析取操作也遵循这样的规则。

这种剪枝是运行时剪枝而非编译期剪枝,但是其逻辑是在编译期赋予的。

3. C语言的逗号运算符

C语言的逗号有着仅次于括号的最差的优先级,且返回其最后一个算式的值。

比如语句y = (x = 4 * 5, x++ * 5), x+25;,在编译期,确定其运行过程如下:

x = 20
x * 5 = 100, 返回至括号前,赋值给y 
(为什么不是x + 25赋值给y呢?因为赋值运算符的优先级高于逗号)
x + 25;

4. printf的取值机制和长度不匹配时的情况

如,以printf输出值时,用%d模式输出一个long int(我们假设int 是16位而long 是32位)会发生什么呢?

注意,由于C语言变长参数传递的历史原因,printf在传参时是将参数反向压栈,故传完参之后第一个参是格式化字符串”%d”,然后程序从右向左地遍历格式化字符串中占位符,以与占位符匹配的长度从栈中弹出相应位数的数据,把它调整为正常顺序,并以占位符的模式解释这些位。既然是弹栈,那么就是从后往前的。这和大端机啥的没啥关系。

比如,以printf("%d", 0x12345678)输出数据时,程序以%d的提示从栈中弹出16位二进制位,弹出结果是8765,逆转为56780101 0110 0111 1000,以有符号整数-补码的模式解释为22136

当然这种做法不值得在实际编码里提倡。

5. C语言union的位机制

C语言union中的各个元素共用同一个首地址(随大端/小端的不同而不同),编辑时按照对应元素的长度和解释模式操作位。

union的大小取决于最长的元素,一般来讲,基于内存对齐要求,它的大小是其所有成员大小的最小公倍数。


Copyright AmachiInori 2017-2021. All Right Reserved.
Powered By Jekyll.
amachi.com.cn