在 C 中以十六进制级别拆分 int?

Split int on hexadecimal level in C?

我正在尝试从图像缓冲区中提取一些颜色代码。当我从缓冲区中读出一个内存地址时,它 returns 一个包含两个像素颜色代码的 int 值。我的目标是将每个颜色代码作为一个单独的 int 值。

例如,当我从图像缓冲区中读出内存地址时,它returns十进制值:142149753。

因为这个十进制值有 9 个字符长,所以我不能简单地将它分解为两个 int 值。因此,我尝试使用 printf 函数将该值转换为十六进制,该函数给出了值:08790879.

现在我可以看到我需要的两个 16 位颜色代码:0879 和 0879。

int firstColorCode;
int secondColorCode;

int colorcodes = IORD_ALTERA_AVALON_PIO_DATA(0x08000000 + 123204);

printf("%08x\n", colorcodes);

如何在代码中将两个颜色代码分别放入对应的int变量中?

免责声明:我是 C 的新手,感觉我在问一个愚蠢的问题:/

您需要使用右移来获取第一个颜色代码。对于第二个颜色代码,您需要使用 uint16_t

进行屏蔽或类型转换
firstColorCode = (uint16_t) (colorcodes >> 16u);
secondColorCode = (uint16_t) colorcodes;

你也可以使用,

firstColorCode = (colorcodes >> 16u) & 0xFFFFu;
secondColorCode = colorcodes & 0xFFFFu;

您应该为颜色代码使用 unsigned int 值,以避免在右移中出现未定义的行为。

uint16_t firstColorCode;
uint16_t secondColorCode;
uint32_t colorcodes; 

此外,正如@lundin 所建议的,我已将 u 添加到常量中,使它们成为无符号常量。

走C型系统雷区有一些基本规则:

  • 在进行任何形式的按位操作时,切勿使用有符号类型。
  • 当您实际上不需要负数时,切勿使用有符号类型。
  • 使用 charshortuint16_t 等小整数类型时要小心,因为它们在表达式中使用时会隐式提升为有符号 int
    有关隐式促销的更多信息:
  • 警惕十六进制文字,因为它们有各种关于获得哪种类型的微妙规则。始终在它们后缀 u 以防止它们成为签名类型。
  • 永远不要在 C 代码中写前导零。如果你在C中写类似0879的东西,它表示八进制格式。

通过更加注意类型,我们可以像这样将您的 32 位数字一分为二:

#include <stdint.h>

uint16_t first;
uint16_t second;

uint32_t colorcodes = IORD_ALTERA_AVALON_PIO_DATA(0x8000000u + 123204u);

first = (uint16_t) (colorcodes >> 16);
second = (uint16_t) colorcodes;

使用 printf("%"PRIx16, first)inttypes.h.

uint16_t 打印为十六进制

只需将数字除以 65536。余数将是你一半的下半部分,商是最重要的部分。

顺便说一句,一些关于使用无符号值的评论的想法也很好,并且考虑将 unsigned int 数字右移 16 相当于除以 2^16 == 65536 .