C++ 任意解引用指针的输出

C++ 任意解引用指针的输出,c++,pointers,x86,arm,memory-alignment,C++,Pointers,X86,Arm,Memory Alignment,我的记忆如下: char buf[8] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; 然后将无符号长指针依次放在前5个字节上,并输出结果: char *c_ptr; unsigned long *u_ptr; c_ptr = buf; for (int i=0;i<5;i++) { u_ptr = (unsigned long *)c_ptr; printf("%X\n",*u_ptr); c_ptr+

我的记忆如下:

char buf[8] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
然后将无符号长指针依次放在前5个字节上,并输出结果:

char *c_ptr;
unsigned long *u_ptr;

c_ptr = buf;
for (int i=0;i<5;i++)
{
    u_ptr = (unsigned long *)c_ptr;
    printf("%X\n",*u_ptr);
    c_ptr++;
}
但是,当我在ARM平台上执行相同的代码时,我得到以下结果:

44332211
11443322
22114433
33221144
88776655
也就是说,它每4个字节绑定一次,并且在这个范围内只解引用4个字节

所以我想问,这种行为(当
指针\u值%4!=0
时)是错误的还是特定于实现的

UPD: 我知道endiannes,我想知道这是正确的,我得到了

11443322
而不是

55443322
例如,当我有指针时
0x10000001

它使地址为
0x10000001
0x10000002
0x10000003
且小于
0x10000000
的字节的无符号长,而不是
0x10000005
,Endianness不能解释这种行为。ARM处理器似乎不允许未对齐四字节边界的四字节内存访问,并且输出指示处理器读取内存,就好像经过四字节边界访问的内存每字节有8位。有关内存对齐的详细信息,请参阅


事实上,在某些体系结构上,如果您尝试执行这种未对齐的内存访问,可能会发生错误。

在怀疑内存对齐后,我快速执行了google=)

该条规定:

在ARMv4架构之前,假定给定的地址用于获取 内容与内存对齐…32位数据提取应具有地址 与32位对齐,依此类推。正如正确猜测的那样,这个问题只是 用于32位和16位数据获取。ARM忽略较低的2位 地址(如果数据提取为32位),并忽略较低的1位if数据 fetch是16位的。因此,如果地址没有正确对齐,那么 那么,数据提取将是错误的

注意最后一句=)

如果您需要x86上所期望的行为,则必须显式地从字符构建整数,即(假设小endian):


如果要从内存中提取一个四字节的字,地址应该是四的倍数


在任何体系结构上,未对齐的访问通常都是一个坏主意。有些会抛出SEGFAULT,有些会透明地处理该故障,然后——非常缓慢地——通过获取包含所需值的两个单词并将它们缝合在一起来合成正确的值。看起来(虽然我不是专家)ARM正在获取指针占用的四字节插槽,并旋转结果,以便寄存器的LSB与指针匹配。

问题在于,您正在取消对非对齐指针的引用,根据硬件的不同,该指针可能未定义。许多体系结构假定
long*
将与32位内存对齐,也就是说,可以被4整除。如果不是,则结果未定义


一般来说,C不能保证当您将一种指针类型转换为另一种指针类型时会发生什么。

到目前为止,每个注释和答案都没有抓住要点。字节不是反转的,而是旋转的。公认的答案解释了发生了什么。在语言层面,我认为问题在于,根据标准,您的程序不是有效的程序,您处于未定义的行为领域:我认为,只有当指针最初是指向
long*
的指针时,将
char*
转换为
long*
才有效,问题是我找不到真正的标准章节,上面的转换是创建非对齐指针的唯一方法。我在一个程序中遇到了问题,其中使用了另一个非对齐指针,所以我想知道,这个问题是因为这个。Endianness不能解释OP提供的输出。ARM处理器默认为little endian。嗯,有点像。Endianness是关于处理器如何存储和读取多字节值。是的,你可以在字节序列和更大的整数类型之间双关,但是处理器不会改变它读取字节的顺序。@DragonLord:大部分的否决票都是通过射击获得的;要求他们离开通常是毫无意义的。与其颠倒你的答案(这会使评论线索变得毫无意义),不如将其删除并(如果你仍然想)添加另一个答案。@Marcelocontos:第一条评论已标记为过时,以解决此问题。谢谢!这就是我想知道的,不用担心。我已经编辑了一些代码,这些代码应该能给出你所希望的行为。谢谢你的回答,我不认为对齐是个问题。
55443322
// Endian-specific
inline unsigned long ulong_at( const char *p ) {
    return ((unsigned long)p[0])
         | (((unsigned long)p[1]) << 8)
         | (((unsigned long)p[2]) << 16)
         | (((unsigned long)p[3]) << 24);
}
// Architecture-specific
inline unsigned long ulong_at( const char *p ) {
    unsigned long val;
    char *v = (char*)&val;
    v[0] = p[0];
    v[1] = p[1];
    v[2] = p[2];
    v[3] = p[3];
    return val;
}