【问题标题】:Access consecutive entries of array in C访问C中数组的连续条目
【发布时间】:2015-12-26 06:04:45
【问题描述】:

假设我有这个:

uint8_t a[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};

如果我:

printf("%lu", ((uint64_t*) a)[0]);

我会得到:

0x0102030405060708

如何使用非标准尺寸做到这一点?前任。 ((uint94_t) a)[0]。 当然,没有uint94_t,这就是我要问的。如何读取非标准位数(甚至字节,它对我也有用)?

注意:我不关心 printf 的特定字符串(因此它可以解析非标准数量的位/字节),但在数据类型中

【问题讨论】:

    标签: c pointers void-pointers


    【解决方案1】:

    "%ul" 表示"%u"(无符号整数)后跟字母"l"。也许您打算使用"%lu"(无符号长),但是对于uint64_t,这两者都不正确。

    正确的说明符在inttypes.h,它是"%" PRIu64

    这也不会像您建议的那样打印0x,它会打印十进制表示。使用"%" PRIx64 表示十六进制(也不会打印前导0x)。


    继续,您的代码会导致 undefined behaviour。根据严格的别名规则,不允许使用uint64_t类型的表达式来访问任何一开始没有写成uint64_tint64_t的变量。

    您可以通过使用正确类型的变量来避免严格的别名规则,无论是在联合中还是在其他地方,例如:

    uint64_t x;
    memcpy(&x, a, sizeof x);
    printf("%" PRIu64 "\n", x);
    

    您的编译器会对此进行优化,因此不必担心它效率低下或其他问题。

    请注意,此输出是实现定义的,因为编译器可以选择各种方式来对 uint64_t 的位进行排序。两种常见的顺序是 big-endianlittle-endian


    您问题的另一部分是关于其他整数类型。不幸的是,您坚持使用编译器提供的内容。很可能它没有提供uint94_t。你必须滚动你自己的代码来实现你想要的。例如,您可以模拟 96 位大端:

    uint8_t a[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C};
    
    uint64_t x = 0, y = 0;
    mempcy((unsigned char *)&x + 4, a, 4); 
    memcpy(&y, a+4, 8);
    printf("%" PRIx64 "%" PRIx64 "\n", x, y);
    

    当然你可以一个字一个字地打印出来。

    【讨论】:

      【解决方案2】:

      在谷歌上搜索了一下,我得到了答案…… 答案是位域!

      typedef union {
          __uint128_t i : 96;
      } __attribute__((packed)) uint96_t;
      printf("%ul", ((uint96_t*) a)[0]);
      

      【讨论】:

      • 注意:这会导致未定义的行为,也不太可能产生 96 位的输出,请尝试使 a 有 12 个字节,就像我上一个示例一样
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      • 1970-01-01
      • 2016-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-21
      相关资源
      最近更新 更多