有人可以澄清我的错误解释吗?我知道我的理解是不正确的,因为我的代码产生了输出(参见问题的底部)。 提前谢谢。
澄清一下,下一行的每个部分是什么意思?:
*(u8 *)((u32)BufferAddress + (u32)i)
它与下一行有什么不同:
*(u32 *)((u32)BufferAddress + (u32)i)
我对上述内容的解释是:
我的解释有什么不对?我认为我缺乏理解是在segment2领域...... cast(u32 *)和(u8 *)有什么区别?
以下代码让我意识到我有一个知识差距:
初始化代码:
main(...) {
...
u8 *Buffer = malloc(256);
...
Buffer[0] = 1;
Buffer[1] = 0;
Buffer[2] = 0;
Buffer[3] = 4;
Buffer[4] = 0;
Buffer[5] = 0;
qFunction(... , Buffer, 6, ...);
...
}
qFunction(... , const u8 *BufferPointer, u32 BufferLength, ...) {
u32 BufferAddress;
...
BufferAddress = (u32) BufferPointer;
...
/* Method 1: */
for (i=0; i < BufferLength; i++)
printf("%d, %p\n", BufferPointer[i], &BufferPointer[i]);
/* Method 2: */
for (i=0; i < BufferLength; i++)
printf("%d, 0x%lx\n", *(u8 *)(BufferAddress+i), BufferAddress+i);
/* Method 3: */
for (i=0; i < BufferLength; i++)
printf("%d, 0x%lx\n", *(u32 *)(BufferAddress+i), BufferAddress+i);
...
}
方法1和方法2的输出正如我所料(两者都相同):
1, 0x1000000
0, 0x1000001
0, 0x1000002
4, 0x1000003
0, 0x1000004
0, 0x1000005
然而,方法3的输出对我来说似乎很奇怪;只有部分结果与方法1/2相同:
-1442840511, 0x1000000
11141120, 0x1000001
43520, 0x1000002
4, 0x1000003
0, 0x1000004
0, 0x1000005
我很感激阅读材料的任何提示或参考。 感谢。
答案 0 :(得分:3)
*(u8 *)((u32)BufferAddress + (u32)i)
*(u32 *)((u32)BufferAddress + (u32)i)
在解除引用之前,顶行将指针强制转换为无符号的8位值,而在解除引用之前,秒将其转换为无符号的32位值。顶行取消反映一个字节,底部取消引用整个4个字节。
解决您的其他问题:
我的解释有什么不对?我觉得我缺乏 理解是在segment2领域......有什么区别 在铸造(u32 *)和(u8 *)之间?
对于顶部和底部代码行,地址长度为32位的解释都是正确的。
答案 1 :(得分:3)
我可以挑剔,然后说“你没有给我们足够的信息”。从技术上讲,这是事实,但它只需要做出一些假设。 u8
和u32
不是标准的C类型,你可以将它们的类型定义为任何东西,但大概是,它们表示无符号的8位值(例如uchar
)和无符号的32位价值(例如unsigned
)。假设,让我们看看你理解的那些,并解释它离开第三个的位置。
BufferPointer是一个const u8 *,这意味着它是一个类型为u8的常量指针。这意味着它指向的数组是8位无符号类型。
现在,BufferAddress
是一个u32 - 这是指针的典型,至少在32位系统上。由于它们总是与总线大小相同,因此在64位系统上,指针是64位。
因此,Method1正在打印数组的元素和数组的地址。那很好很酷。
方法2:
*(u8 *)(BufferAddress + i),BufferAddress + i
BufferAddress是一个无符号整数,您要为其添加值以获取其他地址。这是数组的基本点 - 内存将是连续的,您可以通过提高每个元素的字节数来访问下一个元素。因为它是一个u8数组,所以你只需要前进1.这里有一个问题 - 如果它是一个整数数组,你需要BufferAddress +(i * 4),而不是BufferAddress + i,因为每个int的大小是4字节。顺便说一下,这就是指针运算在C中的工作方式。如果你做了`&amp;(((u32 *)BufferAddress)+ 1)你得到0x100004而不是0x100001,因为你把BufferAddress转换为4byte指针,编译器知道当你看下一个元素时,它必须是4个字节。
所以(BufferAddress+i)
是u8数组的第i个元素的地址。 (u8 *)
将无效整数中的BufferAddress转换为指向u8类型的内存位置的指针,因此当您执行*(u8 *)
时,编译器知道将其视为u8。你可以做(u64 *)
,编译器会说“哦!这个内存区域是64位”,并尝试以这种方式解释这些值。
现在可以清楚地说明方法3中发生了什么。您正在获取每个数组元素的相应地址,但您告诉编译器“将此内存区域视为32位数据”。因此,每次使用*(u32 *)时,您将读取数组的4个字节并将其视为unsigned int。顺便说一下,一旦i> = 3,你就会遇到未定义的行为,因为你正在数组之外阅读。
让我试着想象一下你在那个区域的记忆是什么样的:
0x1000000 = 1
0x1000001 = 0
0x1000002 = 0
0x1000003 = 4
0x1000004 = 0
0x1000005 = 0
对于method2,当i = 2时,你正在查看BufferAddress(= 0x1000000)+ 3,即0x1000002,其中的数字为0。编译器知道它只有一个字节,所以就这样。
但对于method3,当i = 3时,您告诉编译器将其视为32位。因此它看不到'0',它看到0,4,0,0,并使用这些数字得出一个整数值,绝对不会是4。