是否可以在C中的UINT64_T指针中下注?

发布于 2025-02-08 02:32:11 字数 513 浏览 1 评论 0原文

我是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指针,我们用方括号将其索引为第一个字节。这是正确的解释吗?如果是这样,是否可以将其划分为指针,以获取其部分内容而不取消给出。

I'm a C beginner. Having trouble understanding whats happening with this code:

#include <stdio.h>
#include <stdint.h>

int main(void)
{
    uint64_t num = 99999;
    uint64_t *num_ptr = #

    uint8_t first_byte = ((uint8_t *)num_ptr)[0];

    printf("%hhu", first_byte);

    return 0;
}

This prints 159.

I'm looking at uint8_t first_byte = ((uint8_t *)num_ptr)[0];

I'm trying to understand it this way: the uint64_t pointer num_ptr is first cast as a uint8_t pointer, then we index into it with the square brackets to get the first byte. Is this a correct explanation? If so is it possible to index into pointers to get their partial contents without dereferencing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

百合的盛世恋 2025-02-15 02:32:11
  • 99999 = 0x1869f,或者如果您将作为64位数字0000 0000 0000 0001 869F
  • Intel/PC计算机使用Little Endian。 什么是CPU ENDIANNESS?
  • 因此,您的64位数量存储在内存中,AS 9f86 0100100 0000 0000
  • C允许我们通过指向字符类型的指针来检查较大的数据类型字节。 uint8_t是所有非外观系统上的字符类型。
  • (((uint8_t *)num_ptr)[0];将64位指针转换为8位(字符)指针,然后使用[]运算符来删除Reference指针。
  • 我们获得了第一个字节0x9f = 159 dec。
  • %hhu用于打印无符号char。用于uint8_t的最正确的转换说明符,否则将是“%” priu8来自inttypes.h
  • 99999 = 0x1869F or if you will as a 64 bit number 0000 0000 0001 869F
  • Intel/PC computers use little endian. What is CPU endianness?
  • Therefore your 64 bit number is stored in memory as 9F86 0100 0000 0000.
  • C allows us to inspect a larger data type byte by byte through a pointer to a character type. uint8_t is a character type on all non-exotic systems.
  • ((uint8_t *)num_ptr)[0]; Converts the 64 bit pointer to a 8 bit (character) pointer and then uses the [] operator to de-reference that pointer.
  • We get the first byte 0x9F = 159 dec.
  • %hhu is used to print unsigned char. The most correct conversion specifier to use for uint8_t would otherwise be "%" PRIU8 from inttypes.h
冷情妓 2025-02-15 02:32:11

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

#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%02x\n", number.parts[0], number.parts[0] );

    return 0;
}

输出:

number.parts[0] is 159 / 0x9f

在此处使用 c unigon ,它正在模拟它OP代码中所做的。 .parts涵盖与Whole的内存相同。因此,从本质上讲,parts正在访问uint64_t的字节内存中的内容,而无需任何指针删除。

由于 endianness ,因此这种操作将存在具有可移植性问题的问题。当然,可以通过将htonl()之类的函数包装到网络字节顺序中来缓解这种情况,因此保留了已知顺序。

Consider a work-alike program:

#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%02x\n", number.parts[0], number.parts[0] );

    return 0;
}

Which outputs:

number.parts[0] is 159 / 0x9f

Here with a C union, it's simulating what was done in the OP's code. The .parts covers the same memory as the .whole. So in essence the parts is giving access to the content of the uint64_t's bytes-in-memory without any sort of pointer dereference.

This sort of operation will have issues with portability due to endianness, and should generally be avoided. Of course one could mitigate this by packing into network-byte-order with functions like htonl(), so a known order is preserved.

明媚殇 2025-02-15 02:32:11
  1. 您要做的是“指针”。通常,这是一个危险的操作,可能会调用不确定的行为并违反严格的混叠规则。但是,当您以char s访问其他数据时,就可以了。
int main(void)
{
    uint64_t num = 99999;
    uint64_t *num_ptr = #

    printf("%016"PRIx64"\n", num);

    for(size_t index = 0; index < sizeof(num); index++)
    {
        printf("Index = %2zu, value= %02hhx\n", index, ((unsigned char *)num_ptr)[index]);
    }
    return 0;
}

最安全的方法是使用memcpy

int main(void)
{
    uint64_t num = 99999;
    uint64_t *num_ptr = #

    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= %02hhx\n", index, arr[index]);
    }
    return 0;
}
  1. What you do is a "pointer punning". Generally it is a dangerous operation, might invoke Undefined Behavior and violate strict aliasing rule. But when you access other data as chars it is OK.
int main(void)
{
    uint64_t num = 99999;
    uint64_t *num_ptr = #

    printf("%016"PRIx64"\n", num);

    for(size_t index = 0; index < sizeof(num); index++)
    {
        printf("Index = %2zu, value= %02hhx\n", index, ((unsigned char *)num_ptr)[index]);
    }
    return 0;
}

The safest method is to use memcpy

int main(void)
{
    uint64_t num = 99999;
    uint64_t *num_ptr = #

    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= %02hhx\n", index, arr[index]);
    }
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文