uint8_t在达到255后无法正常翻转至0,无法正常工作

Tej*_*hee 9 c stdint uint8t gcc5

我是C-Headers的新手- stdint.hinttypes.h。我正在尝试一些代码以了解uint8_t工作原理。但是,似乎遇到了问题。

我已经声明了4 uint8_t个分别具有边界值0、255、256,-1的整数,并对其执行了一些简单的算术运算。我这样做是因为我想知道C编译器(我在Linux上使用)会产生什么错误/警告gcc 5.4.0。如果不是这样的话,我很想知道输出是什么样子。下面给出的代码。

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

int main() {
        int a = 10;
        printf("%d\n", a++);
        printf("%d\n\n", a);

        // 8 bit unsigned integer -> range[0, 255]
        uint8_t ua81=0, ua82=255, ua83=256, ua84=-1;
        printf("--------STDINT.H----uint8_t--DEMO--------\nua81 = %" PRIu8 "\n", ua81);
        printf("ua82 = %" PRIu8 "\nua83 = %" PRIu8 "\nua84 = %" PRIu8 "\n\n", ua82, ua83, ua84);
        printf("ua81+1 = %" PRIu8 "\nua82-3 = %" PRIu8 "\nua83-4+7 = %" PRIu8 "\nua84-1+20 = %" PRIu8 "\n----------\n\n", ua81+1, ua82-3, ua83-4+7, ua84-1+20);

        return 0;
}
Run Code Online (Sandbox Code Playgroud)

此代码的输出如下:

vagrant@ubuntu-xenial:~/Documents/Coding Practice/p_c$ vi stdint_h.c
vagrant@ubuntu-xenial:~/Documents/Coding Practice/p_c$ gcc -Wall stdint_h.c -o a
stdint_h.c: In function ‘main’:
stdint_h.c:11:33: warning: large integer implicitly truncated to unsigned type [-Woverflow]
  uint8_t ua81=0, ua82=255, ua83=256, ua84=-1;
                                 ^
vagrant@ubuntu-xenial:~/Documents/Coding Practice/p_c$ ./a
10
11

--------STDINT.H----uint8_t--DEMO--------
ua81 = 0
ua82 = 255
ua83 = 0
ua84 = 255

ua81+1 = 1
ua82-3 = 252
ua83-4+7 = 3
ua84-1+20 = 274
----------
Run Code Online (Sandbox Code Playgroud)

如前所述,我正在为此gcc 5.4.0编译器使用Linux计算机。

vagrant@ubuntu-xenial:~/Documents/Coding Practice/p_c$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Run Code Online (Sandbox Code Playgroud)

我不明白为什么对于变量来说ua84,值0在到达后却没有翻转到它255,而对于它却起作用ua83。考虑到255之后的展期,我认为的值ua84应为18

我觉得这与在编译时生成的与变量有关的中提到的隐式截断warning有关ua83。我不知道到底是怎么回事。我也想知道该怎么做,我仍然想继续使用uint8_t

Ser*_*sta 10

由于存在隐式提升,因此ua84-1+20将是an int,其值将为274。您应明确将结果转换为uint8_t18。

printf没有足够的魔力来根据格式(*)转换其参数。它仅期望它收到所需的内容,而只是提取传递的参数。所以在这里你应该写:

    printf("ua81+1 = %" PRIu8 "\nua82-3 = %" PRIu8 "\nua83-4+7 = %" PRIu8 "\nua84-1+20 = %"
            PRIu8 "\n----------\n\n", (uint8_t)(ua81+1), (uint8_t)(ua82-3), (uint8_t)(ua83-4+7),
            (uint8_t)(ua84-1+20));
Run Code Online (Sandbox Code Playgroud)

(*)更确切地说,这是格式说明符的问题。在7.21.6.1段中,针对C11的fprintf函数§7n1570草案说:

hh指定将以下d,i,o,u,x或X转换说明符应用于带符号的char或无符号的char参数(该参数将根据整数提升进行提升,但其值应转换为带符号的char或打印前未签名的字符); ...

因此,如果您明确使用%hhu,则您将获得18(即使已通过274)。但是不幸的是,仅需要inttype.h中的宏才能正确显示期望范围的值,所以许多实现都转换PRIu8u(感谢Eric Postpischil注意到)。

  • @Jabberwocky:恕我直言,它不是标准定义的,因为您没有传递正确的值。“ PRIu8”只能正确显示[0,255]范围内的任何值。对于其他值,最多只能定义实现。 (3认同)
  • 那么printf(“ 300 using PRIu8:%” PRIu8“ \ n”,300);应该打印什么?(https://www.ideone.com/IWhtRT)。是UB IMO。 (2认同)

Sha*_*awn 2

该表达式ua84-1+20使变量ua84经历称为整数提升的过程:它被转换为 an int,然后整个表达式的计算结果为 an int

然后它被打印为无符号 int - 你可能会看到它PRIu8被定义为"u",这当然是期望的unsigned int(并且即使传递了 an ,uint8_t由于可变参数函数如何将其整数参数提升(uint8_t值被提升为int,然后得到unsigned int被视为) printf())。

详细信息: https: //en.cppreference.com/w/c/language/conversion

  • `您可能会看到 PRIu8 被定义为“i”` - 不,我希望是 `%hhu` 。哇,确实是 glibc 中的 `"u"` [inttypes.h](https://github.com/lattera/glibc/blob/master/sysdeps/generic/inttypes.h#L102) (3认同)