【问题标题】:C code: left shift is shifting but dropping top bitsC 代码:左移正在移位但丢弃最高位
【发布时间】:2015-05-20 14:43:22
【问题描述】:

我正在做一个小型嵌入式项目,我通过 SPI 类型接口传输了 40 位。我将这些位从 32 位总线中提取出来,并将高 32 位放入 uint32_t 变量中,将低 8 位放入 uint8_t 变量中。我正在尝试将它们组合成一个uint64_t。但是,当我移动 8 位时,它会丢弃前 8 位。这是我的代码。

uint64_t getError()
{
    uint32_t * disp_addr = (uint32_t*)(MYDISPLAY);

    uint64_t error_upper;
    uint8_t error_lower;
    uint64_t error= 0;

    error_lower = *(disp_addr+1);
    error_upper = *(disp_addr+0);
    error = ((uint64_t) error_upper) <<8 | error_lower;
    return error;
}

此代码可以正常工作,只是它丢弃了我的前 8 位。 任何想法或提示将不胜感激。谢谢。

编辑

uint64_t getError()
{
    uint32_t * disp_addr = (uint32_t*)(MYDISPLAY);

    uint64_t error_upper;
    uint8_t error_lower;
    uint64_t error= 0;

    error_lower = 0x34;
    error_upper = 0xABCDEF12;
    error = ((uint64_t) error_upper) <<8 | error_lower;
    printf("%010x", error);
    //return error;
}

结果: 00cdef1234

【问题讨论】:

  • 期望的行为是什么?
  • 当然在下降.. 他们会去哪里?
  • 在移位前转换高位 var。
  • 它应该在我的 uint64_t 错误的低 40 位中连接 error_upper 和 error_lower。我明白了,如果我左移一个 32 位 int,最高位会下降。但是如果我将它类型转换为 64 位 int 并对其进行移位,它不应该将这些位移动到 33-40 的位置吗?
  • printf("%010x", error); 正在打印00cedf1234printf("%010llx", error); 正在打印 abcedf1234。我想我们可以在这里结束这个问题..

标签: c shift


【解决方案1】:

printf 格式说明符不正确。

#include <stdio.h>

typedef unsigned __int64 uint64_t;
typedef unsigned char uint8_t;

int main(void) {
    uint64_t error_upper, error;
    uint8_t error_lower;

    error_lower = 0x34;
    error_upper = 0xABCEDF12;
    error = (error_upper << 8) | error_lower;
    printf("%x\n", error);
    printf("%llx\n", error);
    return 0;
}

程序输出:

cedf1234
abcedf1234

【讨论】:

  • 当我尝试 printf("%llx\n", error);我得到 500000ffffffffff。
  • @WeatherVane double L 是我使用的。
  • @SparkyGuru 如果我运行这两种格式输出的确切代码。 LP删了他最近的评论,我删了我的回复。
  • %x 需要unsigned int 类型的参数;将它与 uint64_t 参数一起使用具有未定义的行为。 %llx 需要 unsigned long long int 类型的参数;将它与uint64_t 参数一起使用具有未定义的行为除非 uint64_t 被定义为unsigned long long int(通常是这样)。 &lt;inttypes.h&gt;&lt;stdint.h&gt; 中定义的类型定义了 printf 格式的宏——或者您可以转换为 uintmax_t 并使用 %ju: printf("%ju\n", (uintmax_t)x);
  • @KeithThompson 谢谢,我认为您对预期论点的评论最有帮助。我是一个菜鸟程序员。我是一名从事编程工作的 EE 学生。
【解决方案2】:

为什么说高字节被切掉了? 如果我使用你的代码并打印结果是好的:

uint32_t temp = 0x01020304;
uint32_t *disp_addr = &temp;
uint64_t error_upper;
uint8_t error_lower;
uint64_t error= 0;

error_lower = *(disp_addr+1);
error_upper = *(disp_addr+0);
error = (error_upper<<8) | error_lower;

printf("\n%08X%08X\n",  (uint32_t)(error>>32), error);

输出是

0000000102030401

您是否使用%d 打印输出值?

【讨论】:

  • @SparkyGuru AFAIK %X 评估 32 位变量。你的代码是正确的就是你的 fprintf 的问题。
  • 可能,我不明白为什么会这样。有什么方法可以测试吗?
【解决方案3】:

仔细看

uint32_t *disp_addr = &temp;
...
error_lower = *(disp_addr+0);

因为disp_addr 是 uint32_t 的指针,所以您将 32 位值存储在 8 位变量中。根据您的机器字节序以及您加载disp_addr 的方式,您可能加载了错误的数据。

你可能想这样做:

uint32_t *disp_addr = &temp;
...
error_lower = *(uint8_t *)(disp_addr+0);

这是不一样的。

【讨论】:

  • 好评论,买绝对不是答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多