繁体   English   中英

为什么在给变量分配超出范围的值时由编译器决定要分配什么值

[英]why it is up to the compiler to decide what value to assign when assigning an out-of-range value to a variable

在C ++ Primer 4th Edition 2.1.1中,它说“当给有符号类型分配超出范围的值时,由编译器决定要分配的值”。

我听不懂 我的意思是,如果您有类似“ char 5 = 299”的代码,则编译器将生成asm代码,例如“ mov BYTE PTR _sc$[ebp], 43 “(VC)或” movb $43, -2(%ebp) “( gcc + mingw),由编译器决定。

但是,如果我们分配用户输入给出的值怎么办? 例如,通过命令行? 并且生成的asm代码将为“ movb %al, -1(%ebp) ”(gcc + mingw)和“

mov cl, BYTE PTR _i$[ebp]
mov BYTE PTR _sc$[ebp], cl

“(VC),所以现在编译器如何决定将要发生的事情?我认为现在由CPU决定。

你能给我一个清晰的解释吗?

是否由CPU决定由编译器决定。 :)

C ++标准指定了程序的行为方式。 编译器确保实现此行为。 如果您执行标准未指定的操作,则编译器可以执行其喜欢的任何操作。 它可能会产生错误消息,向您的祖母发送电子邮件或破解您的银行帐户。 或者它仍然可以生成代码,是的,然后由CPU决定下一步将发生什么。

但是重点是,CPU不负责确保您的程序按照C ++标准的规定运行。 编译器是。 因此,由编译器决定如何处理与标准的任何偏差(即使它经常选择不做任何特别的事情,但这仍然是编译器的决定)。

当然。 在这种情况下,“由编译器决定”(Stanley Lippman的书)的意思是“它不是由标准强制执行的”。

编译器没有专门决定或不一定生成用于处理这种情况的代码。 它可能取决于平台。

这将是未定义行为的示例。 C ++标准包含许多这样的句子:“如果(某些条件),结果是不确定的行为”。

为什么存在未定义的行为? 不仅会使事情变得更复杂吗? 是的,不幸的是,它确实使程序员变得更加复杂。 UB的原因是简化了编译器编写器的工作-首先使编写器更容易(或根本不可能!),或者通过确定确定性来使编译器更容易实现优化假设。

基本上,编写C ++程序时应遵循许多规则。 编译器可以在编译时很容易地检测到某些违反这些规则的情况,对于这些语言,该语言要求编译器发出错误消息。 例如语法错误。

但是也存在一些编译器难以检测或无法检测到的违规情况。 这样的一个例子是在调用delete后可以继续使用的内存。 理论上讲 ,实际上不可能编写一个程序来检测所有可能的此类违规。 因此,与其要求编译器作者解决检测这些违规问题所无法解决的问题,不如说,C ++标准声明您的程序将遇到“未定义的行为”。 这意味着,你不能让会怎么样任何预测-事实上的标准的例子是,UB可能导致恶魔飞出你的鼻子

[编辑]实际上,正如litb指出的那样,您的具体情况不是未定义行为的示例,而是实现定义的行为的示例,该示例更为文明。 :)此类别描述了C ++标准的作者认识到程序员可以合理预期某种一致行为并且对于编译器编写者来说很难实施的情况,但是要求这种行为将是繁重的或适得其反的在每个实现上都相同。 (例如, sizeof (int)是实现定义的-尽管就C ++标准而言,通常为4或8,但唯一的要求是>= sizeof (short) 。)对于要求标准的编译器一致性,它必须记录在标准中标记为“实现定义的行为”的每种情况下将发生的特定行为。

当然编译器会生成asm代码

您正在将C ++语言与在一个特定平台上的一种可能实现混淆。

我认为这是指这样的情况:

char c = 3456234242424 ;

3456234242424大于签名的char可以容纳的大小,因此它将溢出。 然后应将其设置为char的最大正值还是最小的负值? 语言标准没有强制要求它,因此,由编译器决定要分配的值

对此的另一个常见描述是“依赖于实现”。 语言本身并不要求做什么,但必须做些事情。 因此,实现该语言的编译器可以/必须决定。

对于大多数实现,将int分配给char ,编译器会生成代码,该代码访问int的低位字节,并将其存储在char中。 在您的示例中,命令行输入将存储在大于char的变量中,例如int,然后将其分配给char,从而截断字节。

CPU“永不”失败,也没有决定权,因为它们不可能处理超出范围的值。 在asm代码段中,根本没有关于超出范围的值的信息,一旦正确生成了指令,该信息就不会再出现(如果操作数不适合一个整数的大小,则汇编程序将不会进行汇编)。操作,例如mov al, 123456ABh会引发错误,并且不会生成任何代码,因为没有指令可以使32位值加载到8位寄存器中!)

问题完全取决于编译器和标准规范。 在这种情况下,这意味着当您尝试为无法容纳该变量的变量分配一个数字时,该标准并没有规定确切的行为。因此,编译器实现“决定”了实际发生的情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM