unsigned long long int 的按位运算超过 32 位时不适用
Bitwise operation for unsigned long long int is not applied when it's over 32bits
我只是在 Mac OS X 上做一些测试。但我不明白为什么会这样。
当我尝试对 unsigned long long int 应用一些按位运算时,
当某些操作超过32位时,没有关于该操作的设备。
代码如下..
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define KEY_MAX 31
#define INDEX_MASK 0b11111
unsigned long long int makePlain(unsigned long long int chipherText, int pattern);
static char testArray[] = {
'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y',
'Z', ' ', '@', '@', '@' };
int main(void) {
unsigned int i;
unsigned long long int chipherText = 0b1010100100101010101111001000110101110101001001100111010;
unsigned long long int plain = 0;
for (i = 2; i < 3; i++) {
plain = makePlain(chipherText, i);
int j;
for (j = 0; j < 11; j++) {
printf("IDX=[%d] : %d\n", j,(unsigned int)(plain >> (5 * j) & INDEX_MASK));
}
printf("%c%c%c%c%c%c%c%c%c%c%c\n",
testArray[(unsigned int)((plain >> (5 * 10)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 9)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 8)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 7)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 6)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 5)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 4)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 3)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 2)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 1)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 0)) & INDEX_MASK)] );
}
return 0; }
unsigned long long int makePlain(unsigned long long int chipherText, int pattern) {
int i;
unsigned int temp;
unsigned long long int plain = 0;
for (i = 0; i < 11; i++) {
temp = ((chipherText >> (5 * i)) & INDEX_MASK);
temp = temp ^ pattern;
printf("[%d]:temp -after xor : %d\n", i, temp);
plain |= (temp << (5 * i)); // Here is make problems.
}
return plain; }
(一开始,代码不好看..对不起大家。)
请查看 makePlain 函数的最后一行循环..
当变量i为6时,写位超过32位。
在那之后,"plain |="的所有操作都不适用,但对于超过 32 位的位仍然为 0。
下面是 Xcode 调试器结果。
所以,我只是确认了 asm,然后我找到了那种代码..
call printf
LM42:
movl -4(%rbp), %edx # i -> edx
movl %edx, %eax # eax = i
sall , %eax # i * 4
addl %edx, %eax # i * 5
movl -20(%rbp), %edx # temp -> edx (maybe problem
# becase it load 64bit on 32)
movl %eax, %ecx # eax -> ecx ==> ecx = i * 5
sall %cl, %edx # edx << i * 5 //why 32 bit?
movl %edx, %eax # eax saving (plain) //why 32bit
movl %eax, %eax #
orq>%rax, -16(%rbp) # saving
我认为上面的代码是
plain |= (temp << (5 * i));
关于 makePlain 函数。
我的问题是..
- 为什么会这样? (我认为当它们被移位时它被编译为 32 位寄存器。当我看到 asm 代码时它们加载......)
- 如果我的想法是正确的..什么样的编译选项可以解决这个问题?
- 如何在 Xcode 调试器上查看 assemble 代码?
您的 temp
变量只有 32 位,因为它是一个 unsigned int
。将其类型更改为 unsigned long long
以解决您的问题。
会发生什么?
这一行:
plain |= (temp << (5 * i));
变量 temp
具有 unsigned int
类型,通常是 32 位类型。因此,左移也是一个 32 位的移位,任何超出 32 位的都将被丢弃。当 i
大于 6 时,代码也表现出未定义的行为,因为将值移动比其类型更多的位是未定义的。
有两种方法可以解决这个问题。一种是给 temp
正确的类型,另一种是使用适当的转换来确保转换是 unsigned long long
转换:
plain |= ((unsigned long long)temp << (5 * i));
在编写代码时,请始终确保所有相互依赖的变量都应采用相同的数据类型。它避免了这种情况下的内存溢出
我只是在 Mac OS X 上做一些测试。但我不明白为什么会这样。
当我尝试对 unsigned long long int 应用一些按位运算时, 当某些操作超过32位时,没有关于该操作的设备。
代码如下..
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define KEY_MAX 31
#define INDEX_MASK 0b11111
unsigned long long int makePlain(unsigned long long int chipherText, int pattern);
static char testArray[] = {
'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y',
'Z', ' ', '@', '@', '@' };
int main(void) {
unsigned int i;
unsigned long long int chipherText = 0b1010100100101010101111001000110101110101001001100111010;
unsigned long long int plain = 0;
for (i = 2; i < 3; i++) {
plain = makePlain(chipherText, i);
int j;
for (j = 0; j < 11; j++) {
printf("IDX=[%d] : %d\n", j,(unsigned int)(plain >> (5 * j) & INDEX_MASK));
}
printf("%c%c%c%c%c%c%c%c%c%c%c\n",
testArray[(unsigned int)((plain >> (5 * 10)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 9)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 8)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 7)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 6)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 5)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 4)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 3)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 2)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 1)) & INDEX_MASK)],
testArray[(unsigned int)((plain >> (5 * 0)) & INDEX_MASK)] );
}
return 0; }
unsigned long long int makePlain(unsigned long long int chipherText, int pattern) {
int i;
unsigned int temp;
unsigned long long int plain = 0;
for (i = 0; i < 11; i++) {
temp = ((chipherText >> (5 * i)) & INDEX_MASK);
temp = temp ^ pattern;
printf("[%d]:temp -after xor : %d\n", i, temp);
plain |= (temp << (5 * i)); // Here is make problems.
}
return plain; }
(一开始,代码不好看..对不起大家。)
请查看 makePlain 函数的最后一行循环..
当变量i为6时,写位超过32位。 在那之后,"plain |="的所有操作都不适用,但对于超过 32 位的位仍然为 0。
下面是 Xcode 调试器结果。
所以,我只是确认了 asm,然后我找到了那种代码..
call printf
LM42:
movl -4(%rbp), %edx # i -> edx
movl %edx, %eax # eax = i
sall , %eax # i * 4
addl %edx, %eax # i * 5
movl -20(%rbp), %edx # temp -> edx (maybe problem
# becase it load 64bit on 32)
movl %eax, %ecx # eax -> ecx ==> ecx = i * 5
sall %cl, %edx # edx << i * 5 //why 32 bit?
movl %edx, %eax # eax saving (plain) //why 32bit
movl %eax, %eax #
orq>%rax, -16(%rbp) # saving
我认为上面的代码是
plain |= (temp << (5 * i));
关于 makePlain 函数。
我的问题是..
- 为什么会这样? (我认为当它们被移位时它被编译为 32 位寄存器。当我看到 asm 代码时它们加载......)
- 如果我的想法是正确的..什么样的编译选项可以解决这个问题?
- 如何在 Xcode 调试器上查看 assemble 代码?
您的 temp
变量只有 32 位,因为它是一个 unsigned int
。将其类型更改为 unsigned long long
以解决您的问题。
会发生什么?
这一行:
plain |= (temp << (5 * i));
变量 temp
具有 unsigned int
类型,通常是 32 位类型。因此,左移也是一个 32 位的移位,任何超出 32 位的都将被丢弃。当 i
大于 6 时,代码也表现出未定义的行为,因为将值移动比其类型更多的位是未定义的。
有两种方法可以解决这个问题。一种是给 temp
正确的类型,另一种是使用适当的转换来确保转换是 unsigned long long
转换:
plain |= ((unsigned long long)temp << (5 * i));
在编写代码时,请始终确保所有相互依赖的变量都应采用相同的数据类型。它避免了这种情况下的内存溢出