I'm working on a homework assignment and am probably psyching myself out about this thing a little too much, so I am just seeking some input. Here's the basic code:
for(x = 100; x > 0; x = x + x) {
sum = sum + x;
There are two versions: one where x is a float and one where it is an int. The question is are these infinite loops.
I am thinking that when x is an int, it will eventually overflow, making it less than zero and the loop will stop. When x is a float, x will reach infinity and the loop will be infinite.
Am I close?
The behavior when a signed integer is increased beyond its limit is undefined. So the loop may end or it may be infinite. Or it may crash (or the loop may never run at all). Or as some C gurus like to say, demons may fly out of your nose - though personally I doubt any compiler implementor would go through the trouble of implementing nasal demon functionality.
As far as floating point values are concerned, you are correct that it will be an infinite loop.
When signed integer overflows, the behavior is undefined. Expecting that x will become negative is naive at best.
Some compilers (like GCC) actually implement so called strict value semantics, which means that the compiler takes advantage of that undefined behavior for optimization purposes. In your specific example, the compiler might immediately generate a straightforward infinite loop, i.e. a loop that doesn't have any termination condition at all.
You are indeed correct, integers will overflow to negative values (as long as they're signed) so the loop will end, and floats will stick to "+infinity" which is always greater than any number except NaN.
Edit: I stand corrected, the int version does loop infinitely (on some compilers due to their assumptions): http://ideone.com/HZkht
Related
Integer division by zero is undefined and should result floating point exception and this is what happens why I write the following code
int j = 0 ;
int x = 1 / j;
In this case the program just crashes with FPE, but if I won't use variable and will go with literal values like this int x = 1 / 0; the the program doesn't crash, but just assigns some random value to x ! I tried to detect if int x = 1 / 0; really causes a crash by adding custom SIGFPE handler, but as I thought it is never invoked during literal zero division, but it does when I store 0 in a variable first. So, it seems that the literal zero division never actually crashes the program( I mean the division itself never happens), so does the compiler(GCC in my case) performs any tricks(e.g. substituting 0 with random number) in this case? or I misunderstood something ?
Why integer division by zero doesn't crash the program compiled with gcc?
Well, I think the answer would be: because it can. It can crash. It can not crash.
or I misunderstood something ?
From C11 6.5.5p5 (emphasis mine :p) :
The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.
The behavior is not defined. It is not defined what should happen. It can "crash". It can not crash. It can spawn nasal demons. The program can do anything.
You should write only programs that you know how will they behave. If you want your program to "crash", call abort().
so does the compiler(GCC in my case) performs any tricks(e.g. substituting 0 with random number) in this case?
The only way to know is to inspect the generated assembly code. You could use https://godbolt.org/
Since the expression contains division by zero constant, gcc could handle the issue at compile time.
If the division by variable valued 0, the compiler will give the responsibility to the exception handler because the evaluation is unpredictable.
I am learning to code in C and need to get more familiar with overflow and dealing with large numbers. I need help dealing with the below code.
This isn't my desired output as when I do the calculations on my own, the negative numbers are incorrect. I know it has to do with the larger numbers I'm dealing with. How do I go about approaching this problem? I'm not to sure where to start?
Thanks!
int main() {
unsigned A = 1103624256;
unsigned B = 11254;
unsigned X = 1;
unsigned max_unsigned = (long)(UINT_MAX);
X = ((A*X)+B)%max_unsigned;
printf("X1 =\t%d\n", X);
X = ((A*X)+B)% max_unsigned;
printf("X2 =\t%d\n",X);
X = ((A*X)+B)%max_unsigned;
printf("X3 =\t%d\n", X);
X = ((A*X)+B)% max_unsigned;
printf("X4 =\t%d\n",X);
return 0;
}
my output is:
X1 = 1103635510
X2 = 823626102
X3 = -473507466
X4 = -1793402506
Program ended with exit code: 0
Unsigned Int uses quite often 32 bits. That means, the biggest representable number is 4294967296. This is then max_unsigned in your code.
Your first calculation X = ((A*X)+B)%max_unsigned is therefore 1103624256*1+11254%4294967296=1103635510, which is the result, you are seeing.
In your second calculation the expression A*X is then too big to fit into 32 bits.
That means, your code is illegal, because you do an illegal calculation. This is not covered by the C++ language standard. For example see here: https://en.cppreference.com/w/cpp/language/operator_arithmetic :
When signed integer arithmetic operation overflows (the result does not fit in the result type), the behavior is undefined.
That really means, that anything can happen. The program could behave on Mondays as you expect and on Tuesdays not. The program may crash. Your computer may crash. Your result may be incorrect. The behaviour is just not part of the language specification for C. And therefore the answer to your question must end here. That is the reason why for two years there is not even one answer to the question.
It may be the case that on certain platforms and certain compilers it is possible to predict the behaviour. And you may want to look at the Assembler code to see what happens. But all this is then outside the scope of the C language and therefore not of general interest. C is not a specification language for creating Assembler code. C has rules that must be followed. Otherwise you are not in the scope of C.
It would also not be very professional to speculate more, because in a professional environment you are normally paid to follow rules. And that includes the rules of the programming language.
If you are really interested to see what happens, you have to show the Assembler code and make it a question about Assembler programming. But there is no guarantee that your compiler always produces the same Assembler code for such illegal things. The compiler only guarantees you a predictable result if you follow the rules of the programming language and have no overflows.
Mathematically, 0 / 0 is undefined. But, in C programming (especially gcc compiler gcc-7.3.0 on ubuntu), it produces the answer as 1. I would like to know the reason. Is it working by repeated subtraction? For, the same code, if I use n = 1 / n, I get a floating point exception. However, for gcc-5.3.0, it produces an error.
#include <stdio.h>
int main() {
int n = 5;
n = n - 5;
switch (n) {
case 0:
printf("n= %d", n);
n = n / n;
printf("n calc= %d", n);
break;
case 5:
printf("n=5");
break;
default:
printf("n=1");
break;
}
return 0;
}
Divide by zero is undefined behavior in C programming (C11 6.5.5 ยง6). Meaning that there is no predictable result, there is no telling what your program might do.
It isn't very meaningful to try reason about why you get one particular outcome of "anything might happen". It might print 1, it might print 42, it might print nothing at all. The program might crash and burn. If you run the program twice, you might get different outcomes. And so on.
As for why you won't get a compiler error, the compiler isn't able or obliged to find or diagnose run-time errors. Most cases of undefined behavior need to be avoided by the programmer.
Some good compilers may be able to give warnings if you use pure integer constant expressions such as int x = 0/0;, but again it is not the job of the compiler to find this bug. It is the programmer's job. Therefore you should make a habit of always checking if the right operand of / or % is zero before applying the operands.
Compilers are allowed to assume that the code does not invoke undefined behavior, and use that assumption while optimizing the code.
For any value, other than n==0 the expression n/n evaluates as 1. Since diving by zero is undefined behavior in C, the compiler can assume that this scenario never happens, i.e., it can assume that n!=0.
Since it may assume that, the compiler can replace the slow n/n with the cheap constant value of 1. This is probably what happens with the code in question.
Of course, the compiler is not required to make any such assumption, and might generate an actual division. Depending on the hardware that executes the code, a specific hardware signal (or exception) might be triggered in such a case of division by zero. I doubt that any reasonable compiler will emit division in this example for optimized code, because division is extremely slow, and according to the standard the constant 1 is good enough. However, it is still likely it will produce an actual division in debug mode.
Similar things happen when optimizing away other undefined behavior, such as int overflow:
void f(int x)
{
if (x > x + 1)
// executed only in case of overflow,
// which is undefined behavior,
// and hence likely optimized out.
overflow_error();
...
Don't rely on undefined behavior - it is not predictable.
As can be seen on Godbolt's compiler explorer, both gcc and clang optimize n / n for n integer to evaluate to 1 without any warning. gcc performs this optimisation even at -O0 whereas clang generates the division opcode for -O0 but the optimized alternative for -O1 and above.
0 / 0 has undefined behavior anyway, therefore any behavior for n / n is OK if n is zero, including evaluating to 1 without an observable side-effect.
If you insist, you could qualify n as volatile and the compiler might generate a division, as both gcc and clang do in this case, but as long as n is read twice, it does not have to.
After a discussion with colleagues, I ended up testing wether if clang would optimize two divisions, with a reciprocal to 1, to a single division.
const float x = a / b; //x not used elsewhere
const float y = 1 / x;
Theoretically clang could optimize to const float y = b / a if x is used only as a temporary step value, no?
Here's the input&output of a simple test case: https://gist.github.com/Jiboo/d6e839084841d39e5ab6 (in both ouputs you can see that it's performing the two divisions, instead of optimizing)
This related question, is behind my comprehension and seem to focus only on why a specific instruction isn't used, whereas in my case it's the optimisation that isn't done: Why does GCC or Clang not optimise reciprocal to 1 instruction when using fast-math
Thanks,
JB.
No, clang can not do that.
But first, why are you using float? float has six digits precision, double has 15. Unless you have a good reason, that you can explain, use double.
1 / (a / b) in floating-point arithmetic is not the same as b / a. What the compiler has to do, is in the first case:
Divide a by b
Round the result to the nearest floating-point number
Divide 1 by the result
Round the result to the nearest floating-point number.
In the second case:
Divide b by a.
Round the result to the nearest floating-point number.
The compiler can only change the code if the result is guaranteed to be the same, and if the compiler writer cannot produce a mathematical proof that the result is the same, the compiler cannot change the code. There are two rounding operations in the first case, rounding different numbers, so it is unlikely that the result can be guaranteed to be the same.
The compiler doesn't think like a mathematician. Where you think simplifying the expression is trivial mathematically, the compiler has a lot of other things to consider. It is actually quite likely that the compiler is much smarter than the programmer and also knows far more about the C standard.
Something like this is probably what goes through the optimizing compiler's "mind":
Ah they wrote a / b but only use x at one place, so we don't have to allocate that variable on the stack. I'll remove it and use a CPU register.
Hmm, integer literal 1 divided with a float variable. Okay, we have to invoke balancing here before anything else and turn that literal into a float 1.0f.
The programmer is counting on me to generate code that contains the potential floating point inaccuracy involved in dividing 1.0f with another float variable! So I can't just swap this expression with b / a because then that floating point inaccuracy that the programmer seems to want here would be lost.
And so on. There's a lot of considerations. What machine code you end up with is hard to predict in advance. Just know that the compiler follows your instructions to the letter.
I'm using codeblocks and it is giving a different output to other compilers and I can't find a solution to it.What's the undefined behaviour in this program and is there any solution to avoid it?
This is the code to print the nth number in a number system with only 3 & 4.
#include<stdio.h>
#include<math.h>
int main(void)
{
int n,i,value;
scanf("%d",&n);
value=i=0;
while(n>0)
{
if((n%2)==0)
{
value+=4*pow(10,i);
}
else
{
value+=3*pow(10,i);
}
n=(n-1)/2;
i=i+1;
}
printf("\nThe number is : %d",value);
}
It works fine for numbers upto 6..And the output for numbers greater than 6 is one less than what it actually should be. E.g. if n=7,output=332 where it should be 333.
EDIT : Provided the full code with braces.
you're using the function pow(), which has the signature
double pow(double x, double y);
and calculations as int. Rounding/truncation errors ?
There is no undefined behavior in this code. i=i+1; is well-defined behavior, not to be confused with i=i++; which gives undefined behavior.
The only thing that could cause different outputs here would be floating point inaccuracy.
Try value += 4 * (int)nearbyint(pow(10,i)); and see if it makes any difference.
Seems that floating point gets truncated.
It sounds like a compiler bug.
You are computing the result as value+=3*pow(10,i); but what this actually translates to is value+= (int)(3*pow(10,i));
One of two things might be wrong here:
pow(10,0)!=1.0
cast to int is truncating the result incorrectly.
To debug it easily just try printing the partial results and see there the problem is.
The problem here is most likely that the pow function on this particular platform performs its computations by taking the log of the argument (perhaps natural log; perhaps log base 2), multiplying by the exponent, and then raising the base of the first logarithm to the power of that product. Performing such an operation with infinite-precision numbers would yield a mathematically-correct result, as would performing the operation on extended-precision numbers and returning a double result. My guess would be that the pow function used on this implementation may have been written for a platform which could perform the intermediate computations using extended-precision numbers, and which would consequently return correct double-precision values, but it is being run on a platform which lacks an extended-precision type. As a consequence of this, pow(10,3) may be returning something like 999.9999999997, and coercing that to int yields 999 rather than 1000.
If you're trying to get an integer-type result, there's really no reason to compute the power as a floating-point value. Rather than computing 10^i within the loop, it would be better to have a variable that's initialized to 1 and gets multiplied by 10 each time through the loop.