C 我什么时候可以不使用signed声明int?

C 我什么时候可以不使用signed声明int?,c,types,printf,undefined-behavior,C,Types,Printf,Undefined Behavior,在C中,像-1这样的有符号整数应该用关键字signed声明,如下所示: signed int i = -1; 然而,我试过这样做: signed int i = -2; unsigned int i = -2; int i = -2; 所有3个案例都打印出-2个printf(“%d”,i)。为什么?整数变量的打印方式取决于传递给printf的格式字符串: 如果使用%d,则将其打印为带符号整数 如果使用%u,则将其打印为无符号整数 自从您确认您正在使用以下方式打印: printf("%d",

在C中,像-1这样的有符号整数应该用关键字
signed
声明,如下所示:

signed int i = -1;
然而,我试过这样做:

signed int i = -2;
unsigned int i = -2;
int i = -2;

所有3个案例都打印出-2个
printf(“%d”,i)。为什么?

整数变量的打印方式取决于传递给
printf
的格式字符串:

  • 如果使用
    %d
    ,则将其打印为带符号整数
  • 如果使用
    %u
    ,则将其打印为无符号整数

自从您确认您正在使用以下方式打印:

printf("%d", i);
这是在未签名的情况下。fprintf函数的
7.19.6.1
一节中介绍了这一点,该函数还包括格式说明符的
printf
,第9段中说明:

如果转换规范无效,则行为未定义。248)[…]

3.4.3节
未定义行为中定义的标准如下:

使用不可移植或错误的程序结构或错误的数据时的行为, 本国际标准对其无任何要求

并进一步指出:

可能的未定义行为包括:完全忽略情况并产生不可预测的结果,在翻译或程序执行过程中以环境特有的方式(无论是否发出诊断消息)进行行为,以及终止翻译或执行(发出诊断信息)

最后,我们可以看到int与signed int相同。我们可以通过查看第2段中的
6.7.2
类型说明符一节来了解这一点,它将int分组如下:

int,signed,或signed int

后来第5段说:

每个逗号分隔的集合指定相同的类型,但位字段[…]除外


printf
无法知道传递给它的是什么。C编译器在传递参数时执行默认类型提升,然后函数本身根据传递的格式说明符重新解释值,因为它没有关于传递的值类型的其他信息

当您在
%d
位置将
无符号int
传递给
printf
时,这是未定义的行为。您的程序不正确,它可以打印任何内容


在用2的补码表示法表示负数的硬件上,可能会得到与开始时相同的数字。然而,这不是一个普遍的规则。

您有两件事要做:

unsigned int i = -2; // i actually holds 4294967294
printf("%d", i); // printf casts i back to an int which is -2 hence the same output
  • 有符号和无符号是解释相同64位(或32位或其他)的不同方式
  • Printf是一个可变函数,它接受不同类型的参数
  • 将有符号值(-2)传递给无符号变量,然后要求printf将其解释为有符号

    记住,“有符号”和“无符号”与数字的运算方式有关。 printf系列接受基于格式指示符传入的任何类型的内部强制转换。(这是接受多种类型参数的可变函数的性质。它们不能使用传统的类型安全机制)

    这一切都很好,但并非所有的事情都是一样的

    加法和减法在大多数体系结构上都是一样的(只要你不是在一些不使用2的补码表示负数的古怪体系结构上) 乘法和除法也可以起同样的作用。 不平等性比较是最难知道它们如何工作的,我已经多次在有符号和无符号之间进行比较,我认为这是可以的,因为它们在小符号范围内


    这就是“未定义”的含义。行为由编译器和硬件实现者决定,不能依赖于不同体系结构之间的行为相同,甚至不能依赖于同一体系结构上的行为随时间的推移而相同。

    如何将它们打印出来?
    printf(“%d”)
    使用无符号将是未定义的行为。为什么您认为有符号整数需要
    有符号
    ?我使用了printf(“%d”,I);显示如何打印它。如果是
    printf(“%d”,I)
    然后注意
    %d
    是有符号整数的格式说明符;使用
    %u
    打印无符号值。
    无符号整数i=-2;
    因为隐式转换(按调整范围)请记住这里的
    -
    是一个运算符。simple
    2
    也被签署,对于assign unsigned,您应该这样做:
    unsigned int i=2u
    。请记住
    signed
    unsigned
    之间的重要区别,它们的范围!您所说的未定义行为是什么意思?它打印出来了-2。您的意思是事情可能会发生?@GeorgeNewton是的,任何事情都可能发生,添加链接。@GeorgeNewton:“未定义的行为”,因为它经常用于回答C问题,这意味着C标准对行为没有任何要求。这并不意味着任何事情都可能发生,因为C实现、计算系统、逻辑和物理定律仍然有要求。@GeorgeNewton“未定义的行为”这意味着任何东西都可以打印,包括打印您认为正确的值。但是,这种行为是不可移植的。例如,在负片表示为符号+值的硬件上,打印的数字会有所不同。@Eric Postchil我不得不同意,措辞过于夸张,您的措辞更加精确。There在
    printf(“%d”,i);
    中没有强制转换。也没有转换。在许多C实现中,会将字节重新解释为不同的类型,但C标准不能保证这一点。“将字节重新解释为不同的类型”称为强制转换。不是吗?没有。强制转换是在C 2011(N1570)中定义的6.5.4.他们有形式“(类型)表达”。演员歌剧