简体   繁体   English

如何在 C 中以两种不同的数据类型(uint64_t/uint8_t[8])访问相同的 memory 地址?

[英]How to access same memory address as two different data types (uint64_t/uint8_t[8]) in C?

I would like to access a single memory location with two different datatypes in the C programming language.我想使用 C 编程语言中的两种不同数据类型访问单个 memory 位置。

This is how I want it to be done:这就是我希望它完成的方式:

I make a pointer and allocate 64 bits of memory for it.我创建了一个指针并为其分配了 64 位的 memory。 Then I want to access that memory by using either uint64_t or uint8_t[8] .然后我想使用uint64_tuint8_t[8]访问 memory 。

Using unsigned long long int and unsigned char would not be correct because sizeof(unsigned char)==sizeof(uint8_t) is not always true.使用unsigned long long intunsigned char是不正确的,因为sizeof(unsigned char)==sizeof(uint8_t)并不总是正确的。

I have a feeling that loops and copying memory is not really needed and I think that both我有一种感觉,循环和复制 memory 并不是真正需要的,我认为两者

uint64_t abc = { 0xdeadbeefcafe1337 }

and

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

look the same in memory.在 memory 中看起来相同。

Edit: But why?编辑:但是为什么?

I want to make it easier to do simple addition on int and I would also like to access that int value in a simple array-like fashion, one-byte time.我想让 int 上的简单加法变得更容易,我还想以类似数组的简单方式访问该 int 值,一个字节时间。

you can use unions for that你可以为此使用工会

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.org/z/hkoqFN https://godbolt.org/z/hkoqFN

You can always access an object of any type as an array of characters ( char , unsigned char , or signed char ) and uint8_t is in 99.999% (100%?) cases just an unsigned char .您始终可以将任何类型的 object 作为字符数组( charunsigned charsigned char )访问,并且uint8_t在 99.999%(100%?)情况下只是一个unsigned char

Ie, you can simply do:即,您可以简单地执行以下操作:

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

and use the pointer to inspect or modify abc .并使用指针检查或修改abc

Note that strict aliasing wouldn't allow you to do that with:请注意,严格的别名不允许您这样做:

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

There you'd need a union or memcpy , which would practically get optimized just the same as a direct dereference but the dereference is prohibited to help the compiler with alias analysis which helps with better codegen.在那里你需要一个unionmemcpy ,它实际上会像直接取消引用一样得到优化,但禁止取消引用以帮助编译器进行别名分析,这有助于更好的代码生成。

Going in the reverse direction, ie, accessing (even a properly aligned and properly sized) declared uint8_t array as an uint64_t is also not allowed and it has nothing to do with how the memory would look like and everything to do with alias analysis.反向进行,即访问(即使是正确对齐和适当大小的)声明的uint8_t数组作为uint64_t也是不允许的,它与 memory 的外观无关,与别名分析有关。

ok start from scratch, take a look at this code好的,从头开始,看看这段代码

#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;
}

and after that take a read https://en.wikipedia.org/wiki/Endianness .然后阅读https://en.wikipedia.org/wiki/Endianness Beware do not confuse how the data are stored in cpu register, it is another story.请注意不要混淆数据如何存储在 cpu 寄存器中,这是另一回事。

After that you will get your answer.之后你会得到你的答案。

Cheers干杯

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM