C 有人能解释下面的代码输出吗?

C 有人能解释下面的代码输出吗?,c,C,嗨,我是C编程语言的新手,在变量的数据类型部分,char是一个1字节,它只能容纳一个字符,而int是4字节,它可以容纳-2147483648到2147483647的范围。因此,我试图打破以下程序的大小 #include <stdio.h> int main() { int num = 2147483700; printf("%d", num); return 0; } 我希望出现与大小相关的错误消息。这是超出范围转换的结果。在这种情况下,会尝试在int中

嗨,我是C编程语言的新手,在变量的数据类型部分,char是一个1字节,它只能容纳一个字符,而int是4字节,它可以容纳-2147483648到2147483647的范围。因此,我试图打破以下程序的大小

#include <stdio.h>

int main() {
    int num = 2147483700;
    printf("%d", num);

    return 0;
}

我希望出现与大小相关的错误消息。

这是超出范围转换的结果。在这种情况下,会尝试在int中存储int范围以外的值。因为int是有符号的,所以转换以实现定义的方式进行

在使用负数的2的补码表示的系统上,这通常意味着该值围绕着您在这里看到的值

编译器不需要在发生类似情况时发出警告,但如果愿意,它们可以发出警告。例如,gcc不会使用-Wall-Wextra发出警告,而是使用-Wconversion发出警告

有关整数转换的第6.3.1.8节记录了该行为:

1当整数类型的值转换为其他整数类型时 除了 _Bool,如果该值可以用新类型表示,则该值不变

2否则,如果新类型为无符号,则值为 通过反复加上或减去一个或多个 可以在新类型中表示的最大值 直到值在新类型的范围内

3否则,将对新类型进行签名,并且无法删除该值 在其中有代表性;结果要么是实现定义的,要么是 引发实现定义的信号


这是超出范围转换的结果。在这种情况下,会尝试在int中存储int范围以外的值。因为int是有符号的,所以转换以实现定义的方式进行

在使用负数的2的补码表示的系统上,这通常意味着该值围绕着您在这里看到的值

编译器不需要在发生类似情况时发出警告,但如果愿意,它们可以发出警告。例如,gcc不会使用-Wall-Wextra发出警告,而是使用-Wconversion发出警告

有关整数转换的第6.3.1.8节记录了该行为:

1当整数类型的值转换为其他整数类型时 除了 _Bool,如果该值可以用新类型表示,则该值不变

2否则,如果新类型为无符号,则值为 通过反复加上或减去一个或多个 可以在新类型中表示的最大值 直到值在新类型的范围内

3否则,将对新类型进行签名,并且无法删除该值 在其中有代表性;结果要么是实现定义的,要么是 引发实现定义的信号


出于历史原因,C编译器在默认情况下非常宽容,并且不眨眼地接受愚蠢的错误

建议向编译器请求额外的警告,并使用-Wall-Werror或更严格的设置(如gcc-Wextra或clang-Weverything)生成这些错误

这是我的追踪:

chqrlie$ clang -Wall -Werror overf.c
overf.c:4:15: error: implicit conversion from 'long' to 'int' changes value from 2147483700 to -2147483596 [-Werror,-Wconstant-conversion]
    int num = 2147483700;
        ~~~   ^~~~~~~~~~
1 error generated.

出于历史原因,C编译器在默认情况下非常宽容,并且不眨眼地接受愚蠢的错误

建议向编译器请求额外的警告,并使用-Wall-Werror或更严格的设置(如gcc-Wextra或clang-Weverything)生成这些错误

这是我的追踪:

chqrlie$ clang -Wall -Werror overf.c
overf.c:4:15: error: implicit conversion from 'long' to 'int' changes value from 2147483700 to -2147483596 [-Werror,-Wconstant-conversion]
    int num = 2147483700;
        ~~~   ^~~~~~~~~~
1 error generated.

我排除了与大小相关的错误消息。欢迎来到的奇妙世界。我收到一条消息警告:从“long”到“int”的隐式转换将值从2147483700更改为-2147483596[-Wconstant conversion]@JohnBode这不是仅用于有符号算术溢出吗?除非标准要求编译器打印诊断错误或警告消息,由编译器来决定。对于大多数编译器,许多警告都需要显式启用。GCC和Clang使用-Wall,我还推荐-Wextra和-Wpedantic。MSVC使用/W4。@JohnBode:转换过程中的有符号整数溢出是在C中定义的。C标准要求实现定义其引发C 2018 6.3.1.3的结果或信号。这与表达式求值期间出现的溢出不同,C标准没有为其定义行为6.5 5。我排除了与大小相关的错误消息。欢迎来到的奇妙世界。我收到一条消息警告:从“long”到“int”的隐式转换将值从2147483700更改为-2147483596[-Wconstant conversion]@JohnBode这不是仅用于有符号算术溢出吗?除非标准要求编译器打印诊断错误或警告消息,由编译器来决定。对于大多数编译器,许多警告都需要显式启用。GCC和Clang使用如墙
我还推荐-Wextra和-Wpedantic。MSVC使用/W4。@JohnBode:转换过程中的有符号整数溢出是在C中定义的。C标准要求实现定义其引发C 2018 6.3.1.3的结果或信号。这与表达式求值过程中出现的溢出不同,C标准没有定义行为6.5。他知道他溢出了类型的大小。阅读问题的最后一行:我希望出现一条与大小相关的错误消息。为什么我得到的是不同的数字,而不是编译器告诉我初始值设定项太大了that@Dinesh请参阅我的编辑。编译器不需要就转换发出警告,但可以。不明显的是,整型常量2147483700也有一个类型,由编译器确定。在2^31-1之前,它将具有int类型,然后编译器将尝试将常量的类型设置为更大的类型,例如long或long。因此,我希望从long-long到int之类的隐式转换发出警告,但事实上,编译器没有义务按照C标准给出这样的警告。他知道自己溢出了类型的大小。阅读问题的最后一行:我希望出现一条与大小相关的错误消息。为什么我得到的是不同的数字,而不是编译器告诉我初始值设定项太大了that@Dinesh请参阅我的编辑。编译器不需要就转换发出警告,但可以。不明显的是,整型常量2147483700也有一个类型,由编译器确定。在2^31-1之前,它将具有int类型,然后编译器将尝试将常量的类型设置为更大的类型,例如long或long。因此,我希望从long到int或诸如此类的警告隐式转换,但事实上,编译器没有义务按照C标准给出这样的警告。或者更确切地说,程序员需要学习如何处理警告:相当准确的错误指示。我不认为这是一个宽松的编译器的问题,而是一个草率和不称职的程序员的问题。程序员应该知道倾听警告,而不需要将每个警告都变成错误——不管怎样,每个构建都应该是干净的——没有警告。大多数初级课程/书籍都教授这一点。因此,如果人们在阅读蹩脚的互联网教程时从传统来源学习编程,而不是在自己周围修修补补,那么这个问题就不存在了。@Lundin:令人遗憾的是,编译器过于宽松,OP的示例并没有那么糟糕,一个警告就足够了,但是printfstderr,错误消息\n;肯定会导致错误,而不仅仅是警告。过关-Werror似乎是常识,但没有足够的课程/书籍教授它。是的,静电分析仪有一个完整的市场。如果编译器擅长诊断,那么这个市场就不存在了:或者更确切地说,程序员需要学习如何对待警告:相当准确的错误指示。我不认为这是一个宽松的编译器的问题,而是一个草率和不称职的程序员的问题。程序员应该知道倾听警告,而不需要将每个警告都变成错误——不管怎样,每个构建都应该是干净的——没有警告。大多数初级课程/书籍都教授这一点。因此,如果人们在阅读蹩脚的互联网教程时从传统来源学习编程,而不是在自己周围修修补补,那么这个问题就不存在了。@Lundin:令人遗憾的是,编译器过于宽松,OP的示例并没有那么糟糕,一个警告就足够了,但是printfstderr,错误消息\n;肯定会导致错误,而不仅仅是警告。过关-Werror似乎是常识,但没有足够的课程/书籍教授它。是的,静电分析仪有一个完整的市场。如果编译器擅长诊断,那么这个市场就不存在了: