#include <stdint.h>
#include <iostream>
using namespace std;
uint32_t k[] = {0, 1, 17};
template <typename T>
bool f(T *data, int i) {
return data[0] < (T)(1 << k[i]);
}
int main() {
uint8_t v = 0;
cout << f(&v, 2) << endl;
cout << (0 < (uint8_t)(1 << 17)) << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
g++ a.cpp && ./a.out
1
0
Run Code Online (Sandbox Code Playgroud)
为什么我得到这些结果?
Ste*_*fan 20
它看起来像gcc反转移位并将其应用到另一侧,我想这是一个错误.
在C(而不是C++)中,同样的事情发生了,C转换为asm更容易阅读,所以我在这里使用C; 我还减少了测试用例(删除模板和k数组).foo()是原始的buggy f()函数,foo1()是foo()的行为与gcc一样但不应该,并且bar()显示除了指针读取之外的foo()应该是什么样子.
我是64位,但32位是参数处理和找到k相同的.
#include <stdint.h>
#include <stdio.h>
uint32_t k = 17;
char foo(uint8_t *data) {
return *data < (uint8_t)(1<<k);
/*
with gcc -O3 -S: (gcc version 4.7.2 (Debian 4.7.2-5))
movzbl (%rdi), %eax
movl k(%rip), %ecx
shrb %cl, %al
testb %al, %al
sete %al
ret
*/
}
char foo1(uint8_t *data) {
return (((uint32_t)*data) >> k) < 1;
/*
movzbl (%rdi), %eax
movl k(%rip), %ecx
shrl %cl, %eax
testl %eax, %eax
sete %al
ret
*/
}
char bar(uint8_t data) {
return data < (uint8_t)(1<<k);
/*
movl k(%rip), %ecx
movl $1, %eax
sall %cl, %eax
cmpb %al, %dil
setb %al
ret
*/
}
int main() {
uint8_t v = 0;
printf("All should be 0: %i %i %i\n", foo(&v), foo1(&v), bar(v));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果你的int是16位长,那么你将遇到未定义的行为,结果是"OK".
将N位整数向左或向右移位N位或更多位会导致未定义的行为.
由于这种情况发生在32位整数中,这是编译器中的一个错误.
| 归档时间: |
|
| 查看次数: |
971 次 |
| 最近记录: |