【问题标题】:copy byte-reversed uint64_t to uint8_t array将字节反转的 uint64_t 复制到 uint8_t 数组
【发布时间】:2017-05-05 13:01:24
【问题描述】:

我知道如何反转字节顺序 (convert big endian to little endian in C [without using provided func]) - 在这种情况下,我想使用 __builtin_bswap64

我也知道如何将 64 位 uint 复制到 char 数组 - 最好是 memcopy。 (How do I convert a 64bit integer to a char array and back?)

我的问题是这两者的结合。在问题的根源上,我正在尝试找到此代码的更快替代方案:

carr[33] = ((some64bitvalue >> 56) & 0xFF) ;
carr[34] = ((some64bitvalue >> 48) & 0xFF) ;
carr[35] = ((some64bitvalue >> 40) & 0xFF) ;
carr[36] = ((some64bitvalue >> 32) & 0xFF) ;
carr[37] = ((some64bitvalue >> 24) & 0xFF) ;
carr[38] = ((some64bitvalue >> 16) & 0xFF) ;
carr[39] = ((some64bitvalue >> 8) & 0xFF) ;
carr[40] = (some64bitvalue & 0XFF);

由于 memcopy 不将 __builtin_bswap64 的结果作为源参数(或者是吗?),我尝试了这个:

*(uint64_t *)upub+33 = __builtin_bswap64(some64bitvalue);

但我最终得到了 错误:需要左值作为赋值的左操作数

有没有比我要替换的原始代码更快的替代方法?

【问题讨论】:

  • upub 的类型是什么?您可能违反了严格的别名规则。
  • 你为什么认为它太慢了?你看过汇编代码吗?你有简介吗?首先专注于编写可移植和可读的代码(例如,通过将其包装在一个函数中),仅在遇到速度问题时进行优化。
  • 我确实有速度问题,我知道“过早的优化问题”。不适用于这里。我的假设完全基于直觉,但以*((uint64_t *) upub + 33) = __builtin_bswap64(some64bitval); 为基准,我的直觉被证明是正确的。

标签: c arrays int64


【解决方案1】:

这个:

*(uint64_t *)upub+33 = __builtin_bswap64(PplusQ[di][3]);

解析为

(*(uint64_t *) upub) + 33 = __builtin_bswap64(PplusQ[di][3]);

所以左边是uint64_t,而不是左值。

那么这行得通吗?

*(uint64_t *) (upub+33) = __builtin_bswap64(PplusQ[di][3]);

或者您的意思是像 Aconcagua 评论的那样首先将 upub 转换为 uint64_t *

*((uint64_t *) upub + 33) = __builtin_bswap64(PplusQ[di][3]);

我没有看到提到的upub的类型,所以我不知道。

另外,如果upub 最初指向另一种类型,我感觉aliasing rules 可能存在问题,因此您可能想要使用gcc 的-fno-strict-aliasing 之类的东西或通过联合进行分配,或一次一个字节,如您的第一个代码 sn-p。

【讨论】:

  • 什么是upub?根据声明/设置的方式,这可以并且将调用 UB。
  • @Olaf,我们不知道,问题没有说明。我以为我提到了信息丢失,我还以为我提到了可能的别名问题?我很高兴看到以一种或另一种方式对该主题进行验证。
  • upub/carr 如标题所述是一个uchar/uint8_t 数组。 *(uint64_t *) (upub+33) = __builtin_bswap64(PplusQ[di][3]); 与所有警告、迂腐和其他口哨声完美配合。它也比原始代码更快。
  • @ilkkachu UB 不仅仅是别名!如果您违反有效类型规则,您可能会感到惊讶。
【解决方案2】:

你可以复制为:

uint64_t tmp = __builtin_bswap64(some64bitvalue);
memcpy(upub+33,&tmp,sizeof(tmp));

假设uub是指针变量

【讨论】:

    【解决方案3】:

    在编写与字节序无关的代码时,除了位移之外别无选择。您的代码可能已经接近理想。

    您可以尝试使用循环而不是硬编码数字。类似这样的东西:

    for(uint_fast8_t i=0; i<8; i++)
    {
      carr[i+offset] = (some64bitvalue >> (56-(i*8)) & 0xFF;
    }
    

    与您已有的相比,这可能会变慢或变快或相等,具体取决于系统。总的来说,在没有考虑特定系统的情况下讨论这样的手动优化是没有任何意义的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 2012-10-05
      • 1970-01-01
      相关资源
      最近更新 更多