首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在C中反转long中的字节

在C中反转long中的字节
EN

Stack Overflow用户
提问于 2015-01-24 10:36:06
回答 4查看 886关注 0票数 2

好的,我试着在C中写一个函数来反转一个长的(64字节),并且我得到了一些奇怪的位移位结果。

代码语言:javascript
运行
复制
long  reverse_long(long x) {
    int i;
    for(i=0; i<4; i++) {
            long a = 0x00000000000000FF<<(8*i);
            long b = 0xFF00000000000000>>(8*i);
            a = x&a;
            b = x&b;

            a=a<<8*(7-2*i);
            b=b>>8*(7-2*i);

            x=x&(~(0x00000000000000FF<<(8*i)));
            x=x&(~(0xFF00000000000000>>(8*i)));
            x=x|a;
            x=x|b;
    }
}

在第4行(long a = 0x00000000000000FF<<(8*i)),我在循环的每次迭代中将一个字节的1向左移动8位,这对于第一次、第二次和第三次迭代都很好,但是在第四次迭代时,我得到了类似0xFFFFFFFF000000的东西,而我应该得到0x00000000FF000000

不过,第5行(long b = 0x00000000000000FF>>(8*i))运行得很好,并给出了值0x000000FF00000000

有人能告诉我这是怎么回事吗?

EN

回答 4

Stack Overflow用户

发布于 2015-01-24 10:50:42

a)关于您的错误:

你在那里做什么:

代码语言:javascript
运行
复制
long a = 0x00000000000000FF<<(8*i);

  1. 创建带符号的整型常量0xFF;当它移位3个字节时,
  2. 将其拉出i字节
  3. ,常量变为:

it将其赋给长有符号,执行符号扩展: 0xFF000000 -> extension

b)关于你的代码:有更简单的方法来编写你的函数,例如:

代码语言:javascript
运行
复制
unsigned long reverse_long(unsigned long x) {
  unsigned long rc = 0;
  int i = 8;
  do {
    rc = (rc << 8) | (unsigned char)x;
    x >>= 8;
  } while(--i);
  return rc;
}
票数 1
EN

Stack Overflow用户

发布于 2015-01-24 11:33:25

要了解代码中的潜在问题,您需要了解以下内容:

  1. 整型文字的类型和值
  2. 规则关于左移有符号的值
  3. 规则关于有符号的值右移
  4. 规则关于对有符号的值进行移位
  5. 关于按类型或更多类型的宽度移位值的规则
  6. 超出范围的整数转换的行为

这是相当多的事情需要记住。为了避免处理各种奇怪的问题(例如,当使用i == 3时,long a = 0x00000000000000FF<<(8*i);会导致未定义的行为),我建议使用以下方法:

  • 仅使用无符号变量和常量(包括

类型的正确宽度的x)

  • Use常量

此外,您的代码假定long是64位的。这并非总是正确的。最好是做以下两件事之一:

  • 使您的代码适用于unsigned long,无论unsigned long的大小是什么,请使用
  • 而不是uint64_t

简而言之,如果我们只是修复与我上面列出的点相关的错误(并且不更改算法),那么您的代码应该是这样的:

代码语言:javascript
运行
复制
uint64_t reverse_long(uint64_t x)
{
    int i;
    for(i=0; i<4; i++)
    {
        uint64_t a = 0xFFull << (8*i);
        uint64_t b = 0xFF00000000000000ull >> (8*i);

        a = x&a;
        b = x&b;

        a=a<<8*(7-2*i);
        b=b>>8*(7-2*i);

        x=x&(~(0xFFull<<(8*i)));
        x=x&(~(0xFF00000000000000ull>>(8*i)));
        x=x|a;
        x=x|b;
    }

    return x;   // don't forget this
}

注意:我已经使用ull后缀创建了64位文字。实际上,这只保证了至少64位,但由于这里的所有内容都是无符号的,所以没有区别,多余的位将被截断。更准确地说,用(uint64_t)0xFF代替0xFFull,等等。

票数 1
EN

Stack Overflow用户

发布于 2015-01-24 11:51:09

您已经收到了关于代码哪里出错的很好的建议,但我认为您可能希望看到另一种更简单的逆转方法。

代码语言:javascript
运行
复制
uint64_t reverse_long(uint64_t n) {
    uint8_t* a = (uint8_t*)&n;
    uint8_t* b = a + 7;
    while(a < b) {
        uint8_t t = *b;
        *b-- = *a;
        *a++ = t;
        }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28121740

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档