[英]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_t
或uint8_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 int
和unsigned 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();
}
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 作为字符数组( char
、 unsigned char
或signed 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.在那里你需要一个union
或memcpy
,它实际上会像直接取消引用一样得到优化,但禁止取消引用以帮助编译器进行别名分析,这有助于更好的代码生成。
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.