gpt4 book ai didi

c - 我无法理解结构指针和 XOR 的这种行为

转载 作者:太空狗 更新时间:2023-10-29 15:39:01 25 4
gpt4 key购买 nike

我是第一次使用结构指针,我似乎无法理解这里发生的事情。我的测试应用了 xor 的基本属性,即 x ^ y ^ y = x,但不是在 C 中?

下面的代码在我的主程序中,准确地恢复了“test”的所有字母(我继续在屏幕上打印,但我省略了很多垃圾以使这个问题简短(呃)).结构“aes”指的是这个定义:

typedef uint32_t word;

struct aes {

word iv[4];
word key[8];
word state[4];
word schedule[56];

};

正如上下文所暗示的那样,封装项目是一个 AES 实现(我正在尝试通过尝试新技术来加快我当前的实现)。

在我的测试中,make_string 和 make_state 可靠地工作,即使在有问题的函数中也是如此,但为了引用:

void make_string (word in[], char out[]) {

for (int i = 0; i < 4; i++) {

out[(i * 4) + 0] = (char) (in[i] >> 24);
out[(i * 4) + 1] = (char) (in[i] >> 16);
out[(i * 4) + 2] = (char) (in[i] >> 8);
out[(i * 4) + 3] = (char) (in[i] );

}

}

void make_state(word out[], char in[]) {

for (int i = 0; i < 4; i++) {

out[i] = (word) (in[(i * 4) + 0] << 24) ^
(word) (in[(i * 4) + 1] << 16) ^
(word) (in[(i * 4) + 2] << 8) ^
(word) (in[(i * 4) + 3] );

}

}

无论如何,这是行之有效的 block 。我试图通过将其存放在一个函数中来模块化此功能:

char test[16] = {
'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p'
};

aes cipher;

struct aes * work;

work = &cipher;

make_state(work->state, test);

work->state[0] ^= 0xbc6378cd;
work->state[0] ^= 0xbc6378cd;

make_string(work->state, test);

虽然这段代码可以工作,但通过将它传递给函数来做同样的事情不会:

void encipher_block (struct aes * work, char in[]) {

make_state(work->state, in);

work->state[0] ^= 0xff00cd00;

make_string(work->state, in);

}

void decipher_block (struct aes * work, char in[]) {

make_state(work->state, in);

work->state[0] ^= 0xff00cd00;

make_string(work->state, in);

}

然而,通过删除加密和解密中的 make_state 和 make_string 调用,它可以按预期工作!

make_state(work->state, test);

encipher_block(&cipher, test);
decipher_block(&cipher, test);

make_string(work->state, test);

所以澄清一下,我没有问题!我只想了解这种行为。

最佳答案

char 更改为 unsigned charchar 可能已签名,并且很可能在您的系统上,这会导致在转换为其他整数类型和移位时出现问题。

make_string中的表达式(char) (in[i] >> 24)中,将一个无符号的32位整数转换为一个有符号的8位整数(在您的 C 实现中)。此表达式可能会将值转换为 char 中无法表示的 char,特别是从 128 到 255 的值。根据 C 2011 6.3.1.3 3,结果是引发实现定义或实现定义的信号。

make_state 中的表达式 (word) (in[(i * 4) + 3] ) 中,in[…]char,它是一个带符号的 8 位整数(在您的 C 实现中)。根据 C 2011 6.3.1.1 2 中定义的常用整数提升,此 char 被转换为 int。如果 char 为负数,则结果 int 是负数。然后,当它被转换为无符号的word时,效果是符号位被复制到高24位。例如,如果 char 的值为 -166 (0x90),则结果将为 0xffffff90,但您需要 0x00000090

在整个代码中将 char 更改为 unsigned char

此外,在 make_state 中,in[(i * 4) + 0] 应该在左移之前转换为 word。这是因为它将以 unsigned char 开始,在转换前被提升为 int。如果它有一些设置了高位的值,比如 0x80,那么将它左移 24 位会产生一个不能用 int 表示的值,比如 0x80000000。根据 C 2011 6.5.7 4,行为未定义。

这在大多数 C 实现中不会成为问题;二进制补码通常用于有符号整数,结果将按需要换行。此外,我希望这是编译器开发人员设计的模型情况,因为它是一种非常常见的代码结构。但是,为了提高可移植性,转换为 word 将避免溢出的可能性。

关于c - 我无法理解结构指针和 XOR 的这种行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13710518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com