如何在C语言中以两种不同的数据类型(uint64_tuint8_t[8])访问同一个内存地址?

问题描述 投票:0回答:1

我想在C语言中用两种不同的数据类型访问一个单一的内存位置。

我想这样做。

我做了一个指针,并为它分配了64位的内存。然后我想通过使用以下两种方法访问该存储器 uint64_tuint8_t[8].

使用 unsigned long long intunsigned char 不对,因为 sizeof(unsigned char)==sizeof(uint8_t) 并不总是正确的。

我感觉循环和复制内存并不是真正需要的,我觉得这两种方式

uint64_t abc = { 0xdeadbeefcafe1337 }

uint8_t[8] xyz = { 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37 }

在记忆中看起来是一样的。

编辑:但是为什么呢?

我想在int上更方便地做简单的加法,我也想用类似数组的方式简单地访问该int值,一个字节时间。

c memory types
1个回答
2
投票

你可以使用联合来实现

typedef union 
{
    uint64_t u64;
    uint32_t u32[2];
    uint16_t u16[4];
    uint8_t  u8[8];
}u64;

void foo(void)
{
    u64 u;

    u.u64 =  0xdeadbeefcafe1337ULL;
    for(size_t i = 0; i < sizeof(u.u64); i++)
    {
        printf("byte %02d - 0x%hhX\n", i, u.u8[i]);
    }
}

void foo(void)
{
    u64 u;

    u.u64 =  0xdeadbeefcafe1337ULL;
    for(size_t i = 0; i < sizeof(u.u64); i++)
    {
        printf("byte %02d - 0x%hhX\n", i, u.u8[i]);
    }
}

void bar(void)
{
    u64 *u = malloc(sizeof(*u));

    u -> u64 =  0x1337cafebeefdeadULL;
    for(size_t i = 0; i < sizeof(*u); i++)
    {
        printf("byte %02d - 0x%hhX\n", i, u -> u8[i]);
    }
    free(u);
}

int main(void)
{
    foo();
    printf("-----------------------\n");
    bar();
}

https:/godbolt.orgzhkoqFN


2
投票

你总是可以以字符数组的形式访问任何类型的对象(char, unsigned charsigned char)和 uint8_t 在99.999%(100%?)的情况下,只是一个。unsigned char.

即,你可以简单地做。

uint64_t abc = { 0xdeadbeefcafe1337 };
uint8_t *pabc = (uint8_t*)&abc[0];

然后用指针来检查或修改。abc.

注意,严格的别名不允许你这样做。

uint64_t abc = { 0xdeadbeefcafe1337 };
uint32_t *pabc = (uint32_t*)&abc[0]; 
//^just this is ok but derefing this *pabc would violate strict aliasing

你需要一个 unionmemcpy,这实际上会得到优化,就像直接析出一样,但禁止析出是为了帮助编译器进行别名分析,这有助于更好的代码生成。

在相反的方向,即访问(甚至是一个正确对齐和正确大小的)声明的 uint8_t 阵列作为 uint64_t 也是不允许的,它与内存的外观无关,与别名分析有关。


0
投票

好吧,从头开始,看看这段代码。

#include <stdio.h>
#include <stdint.h>
int main()
{
    uint64_t abc = 0xdeadbeefcafe1337;
    uint8_t xyz[8] = { 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37 };

    printf("%x\n",xyz[0]);
    printf("%x\n",((uint8_t*)&abc)[0]); //is the same of *(uint8_t*)&abc
    return 0;
}

然后读一读 https:/en.wikipedia.orgwikiEndianness。. 注意不要混淆数据是如何存储在cpu寄存器中的,这是另外一回事。

之后,你会得到你的答案。

干杯

© www.soinside.com 2019 - 2024. All rights reserved.