为什么它以十六进制表示法显示?

时间:2016-02-01 08:27:50

标签: c

我尝试使用变量ab进行位算术。当我反转a,其值为0xAF时,结果显示为8位数。 与显示为2位数字的其他数字不同。

我不知道为什么会这样,但是猜猜它与%x显示方式和小端有关?

这是我的代码:

#include <stdio.h>
int main()
{
    int a = 0xAF; // 10101111
    int b = 0xB5; // 10110101

    printf("%x \n", a & b); // a & b = 10100101
    printf("%x \n", a | b); // a | b = 10111111
    printf("%x \n", a ^ b); // a ^ b = 00011010
    printf("%x \n", ~a); // ~a = 1....1 01010000
    printf("%x \n", a << 2);// a << 2 = 1010111100 
    printf("%x \n", b >> 3); // b >> 3 = 00010110 

    return 0;
}

2 个答案:

答案 0 :(得分:6)

考虑到您的int a最有可能是32位,您的a实际上是这样的:

int a = 0xAF; // 0000 0000 0000 0000 0000 0000 1010 1111

因此,如果您翻转所有位,那么

1111 1111 1111 1111 1111 1111 0101 0000

或者,以十六进制

0xFFFFFF50

这正是你得到的。其他只显示2位数字,因为在打印十六进制时省略了尾随零,而其他位操作实际上并没有改变任何前导零。

----感谢@ chqrlie为此---- 如果你真的只想看到结果的8位,你可以做

printf("%hhx \n", ~a); // ~a = 1....1 01010000 --> Output : 50

将打印值限制为unsigned char(8位[在现代操作系统上,不保证,但非常可能用于您的目的])长度。

答案 1 :(得分:4)

这样的代码存在很多潜在的问题。

最重要的是,在进行按位操作时,绝不应使用像int这样的有符号整数类型。因为您可能最终得到意外结果,或者如果在负值整数上使用<< >>之类的运算符,则最终可能会出现未定义/实现定义的行为错误。

所以第一步是确保你有一个无符号整数类型。优选uint32_t或类似stdint.h

另一个相关的问题是,如果在表达式中使用小整数类型,例如uint8_tcharshortbool等,那么它们将隐式获取提升为int类型,这是一种签名类型。即使您使用unsigned charuint8_t,也可以获得相同的效果。这是与按位运算符相关的许多致命错误的来源。

最后,当你需要明确表示类型时,printf系列函数是危险的。虽然这些功能实际上具有零类型安全性,但它们同时采用某种特定类型。如果你给他们错误的类型,你会调用未定义的行为,程序可能会崩溃&amp;烧伤。此外,作为变量参数列表函数,它们还使用隐式的参数提升(默认参数提升),这也可能导致无法预料的错误。

&#34;奇怪&#34;输出您的体验是在签名类型上按位~printf在为unsigned int转换说明符提供时%x的组合。

为了获得更确定的输出,你可以这样做:

#include <stdio.h>
#include <inttypes.h>

int main()
{
    uint32_t a = 0xAF; // 10101111
    uint32_t b = 0xB5; // 10110101

    printf("%.8" PRIx32 "\n", a & b);  // a & b = 10100101
    printf("%.8" PRIx32 "\n", a | b);  // a | b = 10111111
    printf("%.8" PRIx32 "\n", a ^ b);  // a ^ b = 00011010
    printf("%.8" PRIx32 "\n", ~a);     // ~a = 1....1 01010000
    printf("%.8" PRIx32 "\n", a << 2); // a << 2 = 1010111100 
    printf("%.8" PRIx32 "\n", b >> 3); // b >> 3 = 00010110 

    return 0;
}