关于内存对齐C程序两段代码的逻辑与编译问题问询
关于内存对齐学习中代码疑问的解答
问题1:*data8++ = -*data8的逻辑、未定义行为与效率
首先得说,你收到的警告完全合理——这行代码存在未定义行为!
在C标准中,如果同一个表达式里对同一个变量既进行读取操作又进行修改操作,且没有明确的序列点(比如分号、逗号运算符等)来确定执行顺序,编译器可以任意选择执行顺序,结果完全不可预测。具体到这行代码:
*data8++会先读取当前data8指向的值,然后把data8指针加1- 右边的
*-data8是读取当前data8指向的值再取反
但问题是:编译器到底是先执行data8++,再去读右边的*data8?还是先读右边的*data8,再执行指针递增?我们完全没法确定,这就导致代码的行为不可控,运行结果可能和预期完全不符。
至于你问的是否比data8 = data8 +1更优?答案是否定的:
- 首先,这行代码的意图根本不是单纯递增指针——它本来想做的是把当前指针指向的字节取反后赋值回去,再让指针递增,但写法完全错误。
- 正确的写法应该把操作拆分,明确序列点:
这样先读取当前值,再完成赋值和指针递增,完全避免了未定义行为。uint8_t val = *data8; *data8++ = -val; - 从效率上来说,错误的未定义行为代码不会带来任何优化,反而可能让编译器生成混乱的机器码,甚至直接导致运行错误,完全得不偿失。
问题2:Munge16中第二个while循环的作用
这个循环是用来处理总字节数为奇数时,剩下的最后1个字节。
我们来拆解代码里的计算:
size >> 1等价于把size除以2取整数部分——这是因为我们用16位(双字节)来处理数据,所以能处理的完整16位数据块数量是size/2。size & 0x00000001是取size的最低位,结果要么是0要么是1:- 如果
size是偶数,结果为0,此时data8End = data8 + 0,两个指针相等,第二个while循环根本不会执行; - 如果
size是奇数,结果为1,此时data8End = data8 +1,意味着还有1个字节没有被16位处理逻辑覆盖,需要用8位的逻辑单独处理这个剩余字节。
- 如果
举个例子:如果size是5(奇数),那么前4个字节会被第一个while循环以16位为单位处理,剩下的第5个字节就交给第二个while循环来处理。如果size是4(偶数),所有字节都被16位逻辑处理完,第二个循环就跳过了。
内容的提问来源于stack exchange,提问作者NeilB
相关产品推荐
相关产品推荐

