Is it undefined behavior if the intermediate result of an expression overflows?

僤鯓⒐⒋嵵緔 提交于 2019-12-01 06:08:11

Yes, it is undefined behaviour, and the result you get is usually¹ different if unsigned long is a 64-bit type.

¹ It's UB, so there are no guarantees.

Intermediate result

Yes, this is undefined behaviour. What if you just stopped right there and return m? The compiler needs to get from point A to point B, and you've told it to do it by making that calculation (which isn't possible). A compiler may choose to optimize this statement in such a way that you don't get an overflow, but as far as I know, the standard doesn't require the optimizer to do anything.

Why no error when they're variables?

You're explicitly telling gcc not to optimize at all (-O0), so my assumption is that it doesn't know the values of i and j at that point. Normally you'd learn the values because of constant folding, but like I said, you told it not to optimize.

If you re-run this and it still doesn't mention it, there's also the possibility that this warning is generated before the optimizer runs, so it's just not smart enough to do constant folding at all for this step.

user1610015

1) Yes, it's undefined behavior.

2) Because #1 involves variables (not constants), so the compiler in general doesn't know whether it will overflow (although in this case it does, and I don't know why it doesn't warn).

Vinícius Magalhães Horta

You get a warning with two, because the compiler knows the values in the operand. The outputs are right because both use /b which is unsigned long. The temporary value to be divisible by b must be hold greater or equal datatype range, ( i * j ) or ( 100 * 30000000 ) are stored in a CPU register that has the same datatype range of the value to be divided, if b was an int the temporary result would be a int, since b is an ulong, int can't be divided by ulong, the temporary value is stored to an ulong.

It is undefined behavior if it overflows, but it's not overflowing in those cases

A program with the same structure, only changing b to int will have only two lines on .s code.

cltd 
idivl   (%ecx) 

to b = int

movl    $0, 
%edx divl   (%ecx)

to b = unsigned long,

idivl performs signed division, storing the value as signed
divl performs unsigned division, storing the value as unsigned

So you're right, the operation does overflows, the output is correct because of the division operation.

What is the difference of idivl and divl?

https://stackoverflow.com/a/12488534/1513286

As for 5/4 the result is undefined behavior.

However note that if you changed the types to unsigned (for the constants just add the u suffix) not only the values do fit, but according to 3.9.1/4 the arithmetic becomes a modulo arithmetic and the result is perfectly defined even for larger intermediate values that do not fit the type.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!