In C, why this statement- 'i = 5i' compiles & sets 'i' to zero? - c

In GCC the following C code compiles correctly-
int i = 7;
i = 5i;
printf("%d", i);
And prints- 0.
The statement i = 5i clearly makes no sense. Then why on earth the code does not give any compilation error? And why i becomes 0?

This is a GCC extension for representing the imaginary component of complex numbers.
The compiler complains if you compile with -pedantic and -Werror: http://ideone.com/PMlZr5.

Related

Why Valac generates these (meaningless?) temp pointers in C code

I began to study Vala, and now I dont understand why in these examples the variable tmp1 is created if it was possible to use tmp0 at once?
And same with tmp1 tm3 here
I read the documentation a bit but didn't understand why valac generates these temp pointers.
https://wiki.gnome.org/Projects/Vala/Hacking#Documentation
I really want to understand how the Vala compiler works.Now i think that it relies heavily on the optimization that will happen in gcc with -O3 and apparently it is included by default. I tried compiling with the-O3 flag and without, and the weight of the binaries was the same.
The main reason is to avoid undefined behavior. In C, the order arguments are evaluated in is undefined. For example, if you have something like
int x = 1;
foo(x++, x++);
You could be calling foo(1, 2) or foo(2, 1).
In Vala, the order is defined; it will be foo(1, 2). To do this, Vala sometimes needs to use temporary variables, so the code turns into something like:
int x = 1;
int tmp0 = x++;
int tmp1 = x++;
foo(tmp0, tmp1);
To keep the code generator simple, the temporary variables are just always generated.
Any C compiler will optimize the temporary variables away easily (you don't need -O3, -O1 is more than enough for this), so there isn't much reason to change valac to eliminate the temporary variables. The only real downside is that the generated code is a little uglier.

expression did not evaluate to a constant ERROR code

So I am trying to learn C and I am trying to make this code so it will sort of the array's elements from lowest to highest, it's obviously not complete but I just wanted to see the random numbers printed.
Anyway, I am getting an error E0028 & C2131 (Visual Studios) that says "expression must have a constant value" & "expression did not evaluate to a constant." The int goals[howMany];is where VS is telling me I have an error
int main()
{
int i, temp, swapped;
int howMany = 10;
int goals[howMany];
for (i = 0; i < howMany; i++) {
goals[i] = (rand() % 25) + 1;
}
printf("Original List\n");
for (i = 0; i < howMany; i++) {
printf("%d \n", goals[i]);
}
return 0;
}
This is exactly how the code is written out in the tutorial I am watching and they are using Code:Blocks. I know sometimes those two compilers can be different but I was hoping someone can let me know what's going on or how to fix this.
Visual studio doesn't support variable length arrays. C is a little tricky, and the compiler/flags you use matters. For example, if you were to compile with the gcc compiler, using the -std=c99 flag would allow you to run your code with no errors (since -std=c99 supports variable length arrays).
I'm not sure exactly how compilation in Visual Studio works, but that's your problem. I usually don't like C programming in VS for this reason. It's much easier for me to use something like Vim, and compile at the command like so that I can specify compiler settings.
In order to use rand(), you need to include the according lib and then "plant a rand seed" : take a look at C Rand Function
const howMany = 10;
This most likely is just the compiler you are using. I suppose it's a safe guard to prevent a segmentation fault. If howMany variable is changed after being used to initialize the array then a seg fault will will definitely result.A seg fault is when you access something out of bounds. If you try to change a const variable then the compiler will not let you.By making howMany const this will prevent any such errors.

Unusual behavior of pow() in C during compilation

Program file name - armstrong3.c.
#include <stdio.h>
#include <math.h>
int main(void) {
int i, sum, num, rem,x;
x=pow(2,5);
printf("%d\n", x);
printf("List of 3 digit armstrong numbers \n");
for (i=100; i<=999; i++) {
num=i;
sum=0;
while (num>0) {
rem=num%10;
sum=sum+pow(rem,3);
num/=10;
}
if (i==sum)
printf("%d\n", i);
}
return 0;
}
This simple program finds 3 digit armstrong numbers. To calculate the cube I am using pow() of math.h. It didn't work initially and gave the famous error during compilation:
armstrong3.c:(.text+0x91): undefined reference to `pow' collect2:
error: ld returned 1 exit status.
Then I compiled it with gcc armstrong.c -lm, and it worked fine.
Then I used another pow() function in the second line of the main() function and commented out the earlier pow() function which I was using to calculate the cube. Strangely, the program compiled fine with gcc armstrong3.c.
The program posted by me gets compiles fine using gcc armstrong.c -lm.
The following scenario is my current issue:
With the second pow() commented out it gcc armstrong.c compiles with no warnings and errors. No -lm flag required.
If I uncomment the second pow() function in the program, it does not compile and gives the above mentioned error. And with -lm it works fine.
Why is there this unusual behavior with the same function in two places inside the same program?
Compiler: gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04).
Then I used another pow() function in the second line of the main() function and commented out the earlier pow() function which I was using to calculate the cube. Strangely, the program compiled fine with gcc armstrong3.c.
pow is an intrinsic function. When you specify all its arguments as compile time constants, as in pow(2, 5), the compiler replaces the call with its value.
That only happens for integer arguments. Because when you pass floating point arguments the result of pow depends on the current floating point rounding mode, which is not known at compile time.
This behavior is caused by inlining the pow function result in case of constant expressions in its call.

How to make gcc complain about comparison of char with 256

I found the following code on codegolf.stackexchange to print a code table for ASCII characters:
#include <stdio.h>
int main(){
char i;
for(i = 0; i < 256; i++){
printf("%3d 0x%2x: %c\n", i, i, i);
}
return 0;
}
Since chars store single bytes in them, they are always < 256 and the loop never terminates. I would like to detect this upon compilation.
Nicely, clang gives the following warning:
a.c:5:18: warning: comparison of constant 256 with expression of type 'char' is always true [-Wtautological-constant-out-of-range-compare]
for(i = 0; i < 256; i++){
~ ^ ~~~
However, neither gcc nor gcc -Wall give any warning of any sort. Is there any set of command line options I can give to turn on this kind of warnings? Or is it not possible in gcc?
-Wtype-limits (or -Wextra) should trigger this warning
Add -Wextra and -Wconversion. The first includes a warning for your actual probem, but the latter will warn about many other related problems.
But beware: -Wconversion will also warn about many other potential problems if your code is not well-written (signed/unsigned, etc). Best is to compile, see the warnings and carefully verify the listed lines, possibly adding casts (after thinking thrice if the code is correct!).
I compiled the posted code with gcc, on ubuntu 14.04 linux using:
-Wall -Wextra -pedantic -std=c99
and the compiler output this warning:
warning: comparison is always true due to limited range of data type [-Wtype-limits]
Just one more reason to always enable all the warnings when compiling

block statements, commas, and control expressions in C [duplicate]

This question already has answers here:
Are compound statements (blocks) surrounded by parens expressions in ANSI C?
(2 answers)
Closed 9 years ago.
I've tried to read the relavent sections of standard (secs 6.5 and 6.8 of c99), but this lead me to be more confused and without a clear answer. This is the code in question:
#include <stdio.h>
#include <time.h>
int t;
#define block {\
int temp = 1; \
t = time(NULL); \
if (t == (time_t) -1 && temp) puts("turbulance ahead!");\
}
int main(){
if (((block), t%2)) {
puts("nice 'n even");
}
else {
puts("odd..");
}
return 0;
}
Is the code valid c99/c1x? It compiles on clang and gcc without producing any errors, even when -Wall and -Wextra are set.
No. It's not valid under Standard C (C99/C11).
It's valid in GNU C, an extension as called statement expressions.
if (((block), t%2))
This evaluates to a statement expression followed by a comma operator. The return value of a block expression is the value of the last statement in the block. Comma operator evaluates from left to right and its value is equal to the last expression. If you try the -E option in gcc, you will get the preprocessed code, which looks like this:
if ((({ int temp = 1; t = time(((void *)0)); if (t == (time_t) -1 && temp) puts("turbulance ahead!");}), t%2))
So the condition in if statement is solely determined by the value of t%2(as per comma operator).
Is the code valid c99/c1x?
No. C99 generates warning for statement expressions.
It compiles on clang and gcc
No it doesn't. Compile it as the C language, not as the "GNU goo" language.
gcc file.c -std=c99 -pedantic-errors -Wall -Wextra

Resources