C - 是否使用unsigned int只是可怕的编码实践?

B. *_*son -5 c unsigned

是否有任何合法使用无符号数据的例子(即unsigned int)或者应该使用无符号数据类型只是被视为非常糟糕的编码实践,作为20世纪70年代和80年代资源受损平台的遗留物?

考虑一下:

int main ()
{
    unsigned int a = 5;   /*or uint32_t if you prefer*/
    unsigned int b = 8
    unsigned int c = a - b; // I can't even store a subtraction result
                            // from my own data type!

    float f;    // ISO didn't even bother to make a signed version of float.
    double d;   // ISO didn't even bother to make a signed version of double.

    // size_t is an unsigned integer, length varies
    // (4 bytes on 32 bit platforms typically, 8 on 64 bit, ...)
    size_t size1 = 100; 
    size_t size2 = 200;

    // What's a ssize_t -- it's a signed size_t because size_t can't store subtractions.
    // So ssize_t is an bad idea to correct for the bad idea of a size_t being unsigned
    ssize_t size3 = size1 - size3;

    // unsigned operations don't overflow/underflow
    size_t  size4 = size1 - size3; // I don't even underflow, I just wrap.
                                    // Which means unsigned isn't even good
                                    // For use as a pseudo data "validation"
}
Run Code Online (Sandbox Code Playgroud)

另外,memset的C定义,例如:

void * memset ( void * ptr, int value, size_t num );
Run Code Online (Sandbox Code Playgroud)

memset的value参数实际上是一个unsigned char,但是大量函数将unsigned char转换为int只是为了避免使用无符号数据类型或者printf如何将char提升为int.

并且在一个场景中,unsigned用于稍微更大的范围(即32位4GB),这更多地表明正在使用错误的数据类型,并且实际上应该使用int64变量或double来存储值首先.

必须有一些合法使用unsigned,但我想不出一个场景.那么应该使用无符号类型的场景呢?

AnT*_*AnT 8

在这种情况下,拇指规则非常简单:使用无符号类型表示无符号值,使用带符号类型表示有符号值.所以,实际上恰恰相反:大部分时间无偿使用签名类型是一种可怕的编码实践.我甚至可以说代码中的大多数整数类型都应该是无符号的.当然,实际比率将取决于应用程序区域,但对于组合问题和相关域:它是无符号的,无符号的,只有未签名的.

上面的环绕行为示例只是演示了典型的新手编码错误.从本质上说它与流行的没有什么不同

double d = 1/2;
Run Code Online (Sandbox Code Playgroud)

接着是"为什么我d的不是0.5?"之类的东西.

还要注意,在积分计算的领域中,无符号类型通常比有符号类型更有效(除法的C舍入规则与典型的机器支持类型不同,并对签名类型的性能产生负面影响).在混合整数浮点计算中,有符号整数类型可能具有边(FPU指令集通常直接支持有符号整数,但不支持无符号整数).

大量函数将unsigned char转换为int只是为了避免使用无符号数据类型

不.转换为intC语言没有函数原型的过去时代的雏形.所有函数都是在没有原型的情况下声明的(或未声明的),它触发了较小整数参数的自动提升int.一旦标准功能的原型出现,就会有意识地定制以与传统行为兼容.因此,您永远不会看到接受[signed/unsigned] char,[signed/unsigned] short参数(或float就此而言)的"经典"标准库函数.签名与此无关.