1

我正在阅读 C 代码,想知道我是否正确理解了代码。

头文件中定义了一个结构体BF_salt,如下图所示:

typedef
{
BF_WORD salt[4];
..
..
} BF_SALT;

在主 C 代码中,有一个函数调用:

function func1()
{
 static BF_SALT salt;
 func2(salt.salt,x,y);
....
}

func2(BF_WORD * dst,x,y)
{
 unsigned char * dptr= (unsigned char*)dst;
 int c1,c2;

 // c1 and c2 are initialized here.

 // in a loop, an operation similar to the below is performed.

 *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
}

我对上面代码的理解是:

在 func1 中,盐是用结构 BF_SALT 的数据类型定义的。

我们正在调用 func2,传递结构的盐域。

salt 字段是一个包含 4 个元素的数组,每个元素的数据类型为 BF_WORD(32 位字或 4 个字节)

在 func2 中

dst 是指向 BF_WORD 类型元素的数组的名称。

它正在对指针 dst 执行类型转换。

目前,dst 指向数据类型 BF_WORD。它是类型转换的,因此它指向一个 char(1 字节数据)。

现在它正在对整数 c1 和 c2 执行位移操作,并将输出写入 dptr 指向的内存地址。因此,它正在覆盖最初由 dst 指向的数据(盐数组中的字节)。

c1 和 c2 的数据类型为 int,需要 4 个字节的空间。

dptr 会以什么方式覆盖数组的内容?因为每次我们执行 *dptr++,我们都将指针 dptr 前进 1 个字节,因为它指向一个字符。

但是,我们为它分配了一个大于 1 字节的值。数据将如何写入内存?

谢谢。

4

3 回答 3

2

只有结果的最低字节将被写入内存。由于指针指向 char,因此 int 将被截断,并且在转换为左值的类型时会丢失更高的字节;就像您只是将结果分配给 char 变量一样。有关详细信息,请参阅标准部分 6.3.2.1 和 6.5.16.1。

于 2013-02-27T18:15:45.097 回答
1

这里

*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);

执行隐式强制转换unsigned chardptr与 type一样unsigned char *,因此*dptr被视为unsigned char.

于 2013-02-27T18:07:18.440 回答
0

你对上面代码的理解,和我的很像,也让我插播一些自己的想法。

unsigned char * dptr= (unsigned char*)dst;

这里 dst 是 BF_WORD 类型(4 个字节),被向下转换为 char 类型(1 个字节)另外值得注意的是,虽然指针的类型是 char ,并且一次可以导航一个字节,但它确实成立一个 4 字节连续内存位置的地址,因此从技术上讲,它必须能够导航这 4 个字节,一次一个字节。

dptr 会以什么方式覆盖数组的内容?

dptr 现在包含 4 个数字、4 字节数组 salt 的起始地址。所以它当前访问的是 salt[0]。这里 salt[0] 的大小是 4 字节,而 dptr 是 1 字节的指针,因此需要四个 (dptr++) 增量来覆盖数组 salt[0] 的一个元素。

现在另一个问题

我们为它分配了一个大于 1 字节的值。数据将如何写入内存?

*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);

这里 c1 和 c2 都是 int 类型,所以在按位运算之后,结果是 int 类型。因此 4 字节的结果被写入 dptr 指向的 salt[0];在 dptr 的下一个增量中,指针将指向前一个 4 字节 result 的 2 字节,因此前一个结果的最后三个字节将被下一个按位结果溢出。

于 2013-02-27T18:06:47.643 回答