是否可以下标到C中的uint64_t指针?



我是一个C初学者。无法理解这段代码的含义:

#include <stdio.h>
#include <stdint.h>
int main(void)
{
uint64_t num = 99999;
uint64_t *num_ptr = &num;
uint8_t first_byte = ((uint8_t *)num_ptr)[0];
printf("%hhu", first_byte);
return 0;
}

打印159

我在看uint8_t first_byte = ((uint8_t *)num_ptr)[0];

我试图这样理解它:uint64_t指针num_ptr首先被转换为uint8_t指针,然后我们用方括号索引它以获得第一个字节。这个解释正确吗?如果是这样,是否有可能索引到指针,以获得他们的部分内容没有解引用?

  • 99999=0x1869F或者如果您愿意,则为64位数字0000 0000 0001 869F
  • Intel/PC电脑使用小端序。什么是CPU端序?
  • 因此,您的64位数字存储在内存中为9F86 0100 0000 0000
  • C允许我们通过指向字符类型的指针逐字节地检查更大的数据类型。uint8_t是所有非外来系统的字符类型。
  • ((uint8_t *)num_ptr)[0];将64位指针转换为8位(字符)指针,然后使用[]运算符对该指针进行解引用。
  • 我们得到第一个字节0x9F= 159 dec
  • %hhu用于打印unsigned charuint8_t最正确的转换说明符应该是inttypes.h
  • 中的"%" PRIU8

考虑一个类似工作的程序:

#include <stdio.h>
#include <stdint.h>
typedef union td_USixtyFour
{
uint64_t whole;
uint8_t  parts[sizeof(uint64_t)];
} USixtyFour;

int main( int argc, char **argv )
{
USixtyFour number;
number.whole = 99999;
printf( "number.parts[0] is %u / 0x%02xn", number.parts[0], number.parts[0] );
return 0;
}

输出:

number.parts[0] is 159 / 0x9f

在这里使用C联合,它模拟了OP代码中的操作。.parts.whole覆盖相同的内存。因此,本质上,parts允许访问uint64_t的内存字节,而不需要任何类型的指针解引用。

这类操作会因为端序而导致可移植性问题,通常应该避免。当然,可以通过使用htonl()之类的函数将其打包成网络字节顺序来缓解这种情况,这样就保留了已知的顺序。

  1. 你所做的是一个"指针双关语"。通常这是一个危险的操作,可能会调用未定义行为并违反严格的混叠规则。但是当您访问其他数据作为chars时,它是OK的。
int main(void)
{
uint64_t num = 99999;
uint64_t *num_ptr = &num;
printf("%016"PRIx64"n", num);
for(size_t index = 0; index < sizeof(num); index++)
{
printf("Index = %2zu, value= %02hhxn", index, ((unsigned char *)num_ptr)[index]);
}
return 0;
}

最安全的方法是使用memcpy

int main(void)
{
uint64_t num = 99999;
uint64_t *num_ptr = &num;
unsigned char arr[sizeof(num)];
printf("%016"PRIx64"n", num);
memcpy(arr, &num, sizeof(num));
for(size_t index = 0; index < sizeof(num); index++)
{
printf("Index = %2zu, value= %02hhxn", index, arr[index]);
}
return 0;
}

相关内容

  • 没有找到相关文章

最新更新