【问题标题】:Using unsigned data types in C在 C 中使用无符号数据类型
【发布时间】:2017-09-14 10:57:07
【问题描述】:

如何正确使用 unsigned int?当用户输入a 小于b 时,我的函数unsigned int sub(int num1, int num2); 不起作用。如果我简单地使用 int,我们可以期待一个否定的答案,我需要在减去之前确定哪个更大。我知道这很容易,但也许有办法使用 unsigned int 来避免这种情况?

例如,当a = 7 和b = 4 时,答案是 3.000000。但是当我翻转它们时,代码给了我 4294967296.000000 我认为这是一个内存地址。

#include <stdio.h>

unsigned int sub(int num1,int num2){
    unsigned int diff = 0;
    diff = num1 - num2;
    return diff;
}

int main(){
    printf("sub(7,4) = %u\n", sub(7,4));
    printf("sub(4,7) = %u\n", sub(4,7));
}

输出:

sub(7,4) = 3
sub(4,7) = 4294967293

【问题讨论】:

  • 从有符号转换为无符号不会导致采用绝对值。它会导致modular arithmetic 转换。
  • 您期望从 a=4, b=7 案例中得到什么?
  • @Cornstalks 啊,你是对的,绝对值一定是最好的方法
  • 几乎所有发布的代码都不相关,而 相关的部分取决于您未显示的用户输入。至少说出你想要什么输出。
  • 是的,unsigned 的意思是没有符号,也就是说不能为负数。如果需要允许负值,则不能使用unsigned。出于兴趣,您认为这是什么意思?

标签: c int unsigned


【解决方案1】:

无符号数是无符号...这意味着它们不能为负数。 相反,它们会换行(下溢或上溢)。

如果你做一个8位无符号的实验,那么你可以看到0减去1的效果:

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

int main(void) {
    uint8_t i;

    i = 1;

    printf("i: %hhu\n", i);

    i -= 1;

    printf("i: %hhu\n", i);

    i -= 1;

    printf("i: %hhu\n", i);

    return 0;
}
i: 1
i: 0
i: 255

255 是 8 位无符号可容纳的最大值 (2^8 - 1)。


然后我们可以使用您的4 - 7 对 32 位无符号进行相同的实验:

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

int main(void) {
    uint32_t i;

    i = 4;

    printf("i: %u\n", i);

    i -= 7;

    printf("i: %u\n", i);

    return 0;
}
i: 4
i: 4294967293

4294967293 实际上是0 - 3,它会换行到2^32 - 3


您还需要注意将整数值(sub() 函数的返回类型)分配给 float... 通常这是要避免的。

见下文。 x()unsigned int 的形式返回4294967293,但它存储在float 中......然后这个float 被打印为4294967296???

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

unsigned int x(void) {
    return 4294967293U;
}

int main(void) {
    float y;

    y = x();

    printf("y: %f\n", y);

    return 0;
}
y: 4294967296.000000

这实际上与float的精度有关...不可能将绝对值4294967293存储在float中。

【讨论】:

  • 感谢您提供非常详细的解释。请问uint8_t是什么类型的标识符?
  • @reiallenramos uint8_t 是由#include &lt;stdint.h&gt; 定义的精确8 位宽的无符号整数类型。如果实现没有可用的此类类型,则它是可选的。
【解决方案2】:

“a 和 b 之差的绝对值”不适用于a,b 的许多组合。任何溢出的a-b 都是未定义的行为。显然abs(INT_MAX - INT_MIN) 不会生成正确答案。

此外,使用abs() 会调用未定义的行为,选择值为int。当-INT_MIN 不能表示为int 时,abs(INT_MIN) 是未定义的行为。

要计算2个int的绝对值差,将它们减去unsigned

unsigned int abssub(int num1,int num2){
  return (num1 > num2) ? (unsigned) num1 - num2 : (unsigned) num2 - num1;
}

【讨论】:

    【解决方案3】:

    unsigned int 不能用于表示负变量。我相信您想要的是找到ab 之间差异的绝对值。如果是这样,您可以使用stdlib.h 中的abs() 函数。 abs() 函数接受int 变量i 并返回i 的绝对值。

    unsigned int 在您的情况下返回一个巨大数字的原因是由于整数在系统中的表示方式。您将diff 声明为int 类型,该类型能够存储负值,但表示-3 的相同位序列在解释为unsigned int 时表示4294967296

    【讨论】:

      【解决方案4】:

      你看到的叫做无符号整数溢出。正如您所指出的,无符号整数不能包含负数。所以当你尝试做一些会导致负数的事情时,可能会发生看似奇怪的事情。

      如果您使用 32 位整数,

      • int (int32_t) 可以容纳介于 (-2^31) 和 (+2^31-1) 之间的数字,INT_MININT_MAX
      • unsigned int (uint32_t) 可以容纳介于 (0) 和 (2^32-1)、UINT_MINUINT_MAX 之间的数字

      当您尝试向 int 添加一些会导致数字大于该类型可以容纳的数字时,它将溢出

      【讨论】:

      • 这是很好的信息,但它没有回答我的问题,所以我不能选择这个作为 the 答案
      • @reiallenramos 你想要什么?要将 unsigned 值打印为 -3?
      • @chux 不,我想删除 - 符号,这已经通过使用其他 cmets 的 abs() 解决了
      • @reiallenramos abs() 也有它的problems
      • @chux 喜欢什么?出于我的目的,我只是坚持 int 声明,然后在函数定义中使用 abs()。
      【解决方案5】:

      变成负数,无符号数据类型不包含负数,所以变成大数

      【讨论】:

        猜你喜欢
        • 2014-05-25
        • 1970-01-01
        • 2014-10-16
        • 2017-04-05
        • 2012-01-23
        • 1970-01-01
        • 2014-02-01
        • 1970-01-01
        • 2011-01-22
        相关资源
        最近更新 更多