Which variable should be optimize in following C code - c

If your compiler actually optimizes access time of only two registers variables per function, which two variable in the following program are the best one to be made into register variables?
void main(void)
{
int i,j,k,m;
do
{
printf("enter value");
scanf(“%d”,&i);
m=0;
for(k=0;k<100;k++)
m=k+m;
}
while(i>0);
}
Please ignore if any mistake is there...

Trick question? In a smart compiler, none of the variables are registerized. i has its address taken, so it can't be in a register all the time. j, k and m should be optimized away.

Certainly not j, since it is never used. Not i either, as you are using the address-of operator to write to it, which means it needs to be read back from memory after it's been written by the scanf. That only leaves k and m.

Good compiler will optimize this part of code:
m=0;
for(k=0;k<100;k++)
m=k+m;
And replaced it with m = 4950; :)
The better one will optimize m = 4950; and put nothing in place). j also will be optimized. And i can't be register because in scanf its address is needed. So final answer is "NO ONE".

I'd guess the compiler would pick k and m

Since the result of the computation is never used the compiler can optimize out almost all of your code. The only things that must remain are equivalent to
int main(void) {
int i;
do {
printf("enter value");
scanf(“%d”,&i);
} while(i>0);
return 0;
}
As others have already said the only remaining variable i can't be of register storage class since its address is taken.

Related

Understanding the reason behind a output

I am a beginner is Computer Science and I recently started learning the language C.
I was studying the for loop and in the book it was written that even if we replace the initialization;testing;incrementation statement of a for loop by any valid statement the compiler will not show any syntax error.
So now I run the following program:
#include<stdio.h>
int main()
{
int i;
int j;
for(i<4;j=5;j=0)
printf("%d",i);
return 0;
}
I have got the following output.
OUTPUT:
1616161616161616161616161616161616161616.........indefinitely
I understood why this is an indefinite loop but i am unable to understand why my PC is printing this specific output? Is there any way to understand in these above kind of programs what the system will provide us as output?
This is a case of undefined behaviour.
You have declared i so it has a memory address but haven't set the value so its value is just whatever was already in that memory address (in this case 16)
I'd guess if you ran the code multiple times (maybe with restarts between) the outputs would change.
Some more information on uninitialized variables and undefined behaviour: https://www.learncpp.com/cpp-tutorial/uninitialized-variables-and-undefined-behavior/
Looks like i was never initialized, and happens to contain 16, which the for loop is printing continuously. Note that printf does not add a new line automatically. Probably want to read the manual on how to use for.
To better understand what is going on, you can add additional debugging output to see what other variables are set to (don't forget the \n newline!) but really problem is the for loop doesn't seem right. Unless there's something going on with j that you aren't showing us, it really doesn't belong there at all.
You are defining the variable i but never initializing it, instead, you are defining the value for j but never using it.
On a for loop, first you initialize the control variable, if you haven't already done it. Then you specify the condition you use to know if you should run another iteration or not. And last but not least, change the value of the control variable so you won't have infinite loops.
An example:
#include <stdio.h>
int main()
{
// 1. we declare i as an integer starting from 1
// 2. we will keep iterating as long as i is smaller than 10
// 3. at the end of each iteration, we increment it's value by 1
for (int i = 1; i < 10; i++) {
printf("%d\n", i);
}
return 0;
}

Global variable reads inside tight loops in C

Say I have a tight loop in C, within which I use the value of a global variable to do some arithmetics, e.g.
double c;
// ... initialize c somehow ...
double f(double*a, int n) {
double sum = 0.0;
int i;
for (i = 0; i < n; i++) {
sum += a[i]*c;
}
return sum;
}
with c the global variable. Is c "read anew from global scope" in each loop iteration? After all, it could've been changed by some other thread executing some other function, right? Hence would the code be faster by taking a local (function stack) copy of c prior to the loop and only use this copy?
double f(double*a, int n) {
double sum = 0.0;
int i;
double c_cp = c;
for (i = 0; i < n; i++) {
sum += a[i]*c_cp;
}
return sum;
}
Though I haven't specified how c is initialized, let's assume it's done in some way such that the value is unknown at compile time. Also, c is really a constant throughout runtime, i.e. I as the programmer knows that its value won't change. Can I let the compiler in on this information, e.g. using static double c in the global scope? Does this change the a[i]*c vs. a[i]*c_cp question?
My own research
Reading e.g. the "Global variables" section of this, it seems clear that taking a local copy of the global variable is the way to go. However, they want to update the value of the global variable, whereas I only ever want to read its value.
Using godbolt I fail to notice any real difference in the assembly for both c vs. c_cp and double c vs. static double c.
Any decently smart compiler will optimize your code so it will behave as your second code snippet. Using static won't change much, but if you want to ensure read on each iteration then use volatile.
Great point there about changes from a different thread. Compiler will maintain integrity of your code as far as single-threaded execution goes. That means that it can reorder your code, skip something, add something -- as long as the end result is still the same.
With multiple threads it is your job to ensure that things still happen in a specific order, not just that the end result is right. The way to ensure that are memory barriers. It's a fun topic to read, but one that is best avoided unless you're an expert.
Once everything translated to machine code, you will get no difference whatsoever. If c is global, any access to c will reference the address of c or most probably, in a tight loop c will be kept in a register, or in the worst case the L1 cache.
On a Linux machine you can easily generate the assembly and examine the resultant code.
You can also run benchmarks.

Unused Variable Error

I am new to programming and I am currently learning the C language. This is my code. I have tried different fixes, such as making sure I have my semicolons. However, when I go to check my code in the online compiler, I always get unused variable and data definition has no type or storage class. Any information would help me, I assure you, so please let me know what you think a possible solution could be.
//C code
//This program will calculate the average speed of passing cars using a WHILE-END loop
//Developer: Jasmine Tucker
//Date: 7 Sept 2014
#include <stdio.h>
Int main ()
{
/* define variable */
int average_speed;
int car_count;
int car_speed;
};
/* set variable values */
average_speed= 0;
car_count=0;
car_speed=0;
/*WHILE-END loop */
WHILE (car_count > 0)
{
printf (“Enter the car’s speed %s:”, car_count);
scanf (“%d”, & car_speed);
average_speed= car_speed/ car_count
car_count++;
}
printf (“\n The average speed is %d miles per hour. \n”, (average_speed));
return 0;
}
A Few Things:
Int main()
should be
int main()
This is perhaps an easy typo, or the unfortunate side effect of a grammar check.
You could probably do well by studying the standard types in C.
Modifiers aside, there are not very many, and except for special types, _Bool, _Complex, _Imaginary, they are lowercase. (The same holds true for keywords).
Storage class refers to something less commonly used, or at least out of the scope of this program (auto,register,static,extern).
The following definitions use the int type as well, so I will reproduce them here [sic].
/* define variable */
int average_speed;
int car_count;
int car_speed;
};
/* set variable values */
average_speed= 0;
car_count=0;
car_speed=0;
As others have mentioned, there is an extraneous curly brace after the three variables are declared. };
(Notice how sad he looks.)
If you are coming from a language that requires semi-colons after curly braces, you have some hard habits to break.
In any case, commenting that out should remove several errors:
/* }; */
as this is effectively closing the block for main().
As user haini pointed out, you could actually pull the variable definitions outside of main(), allowing them to be accessible to any function. (Use across source files would bring up the aforementioned extern).
Some programmers use special varaible [pre|suf]fixes to distinguish global from local variables.
int g_average_speed;
int g_car_count;
int g_car_speed;
As these variables need to be initialized before use, you can do this in the definition:
int g_average_speed = 0;
int g_car_count = 0;
int g_car_speed = 0;
Often, the use of global variables is discouraged, preferring instead parameter-based sharing of variables, which makes more sense once you introduce multiple functions.
As mentioned, 'WHILE' is not a keyword, while while is. As with the variable types, the list of keywords is very short, and mostly lowercase. It is good to know the keywords so as to avoid using them for variable/function naming.
As far as logic is concerned, your while-loop will never begin, as the expression car_count > 0 will not be satisfied as you've initialised car_count to 0.
While it's easy to hard-code a value, you may probably want to set another variable such as max_cars to an upper limit and check for car_count < max_cars. (Don't forget you're counting from 0).
/* define variable */
int max_cars = 10;
/* rest of variables, init */
while( car_count < max_cars )
Now, aside from the interesting quotations '“' which will give you trouble, and the missing semicolon at average_speed = car_speed / car_count as pointed out again by haini, you should try to step through your loop mentally. Don't ever forget that users are inherently evil and will attempt possibly unforseen values when allowed to interact with the program (scanf()). Negative values and 0 are not out of the question with int and %d, though you may expect some cars to be 'parked' and thus speed 0. Down the line, the unsigned modifier and %u may be of use.
In any case, it's good to get in the habit of sanitizing user input, and/or giving the user an option to opt-out (i.e. "TYPE -1 to break..." ), and checking for invalid or exit codes with an if. (break may be the keyword to pursue in this case)
Your average_speed calculation doesn't quite seem right. Don't forget you're storing values into integers, so you're gonna have some rounding errors.
First think about what happens when your initial case arrives -- what is car_count, and what happens when you divide by that value?
Then, think about the final case, (assuming your upper boundary is 10) in which car_count == 9. You will be assigning car_speed / car_count to average_speed. Is this really what you want?
You can minimize rounding errors and more difficult calculation by maybe 'keeping track' of the total of the speeds, and only one average calculation.
/* define variable */
int total_speed = 0;
In your while loop:
total_speed += car_speed;
or
total_speed = total_speed + car_speed;
And then outside of the loop:
average_speed = total_speed / (car_count - 1);
(The adjustment to car_count is necessary because the value increments after the final loop.)
NOTE: in this limited example, the average_speed variable may not be necessary, unless used outside of the printf().
There are a few issues in your code that I see.
The code will never get in the while loop. If you initialize it to 0, it will never be greater than 0, so will never enter the loop.
Even if it gets into the loop, this is an infinite loop. Keep adding one to a variable would make it so the variable is always greater than 0, so will never exit the loop.
MAJOR ONE: your variables are inside main, but you are using them outside of main!
#include <stdio.h>
Int main ()
{
/* define variable */
int average_speed;
int car_count;
int car_speed;
**};**
(Not sure about this one) but you have an uppercase I in the word int in your method declaration, and uppercase WHILE, should be while.
Code that is not within the main() function causes your errors.
//C code
//This program will calculate the average speed of passing cars using a WHILE-END loop
//Developer: Jasmine Tucker
//Date: 7 Sept 2014
#include <stdio.h>
/* define variable */
//You Can define global variables or local variables. If you want to use them outside your
//function you Need to declare them globally as done here
int average_speed;
int car_count;
int car_speed;
//This is where the Magic happens. If you execute your program it will jump to the main
//function and execute whatever is in there
int main ()
{
/* set variable values */
average_speed= 0;
car_count=0;
car_speed=0;
/*WHILE-END loop */
//The while Loop is not a function, you Need to put it in main() so it gets executed
while(car_count > 0)
{
//You did use very strange signs here. The correct ones are These: ""
printf("Enter the car’s speed %s:", car_count);
scanf("%d", &car_speed);
average_speed= car_speed / car_count; //You Forget a semicolon indeed ;-)
car_count++;
}
printf("\n The average speed is %d miles per hour. \n", average_speed);
return 0;
} //semicolons at the end of a function are not used in C. They are used if you want to define a structure.
I strongly suggest that you start off with basic books / a wiki to C programming. Here is a good (at least it was for me) start into that: http://en.wikibooks.org/wiki/C_Programming/Intro_exercise

Why is my variable not being updated?

I have defined a variable with an initial value.
When stepping through the code:
I can see the initial value
My function changes the value
When I use the variable later it has the wrong value
What is happening?
Note: this is intended as a reference question for common problems. If the generic answers here don't help you, post a question containing your complete, actual code.
There are several reasons why a variable might not keep a value. While some are arcane and difficult to debug, some of the most common reasons include:
The variable is modified by an interrupt
//---in main()---
unint8_t rxByte = 0;
printf("%d", rxByte); //prints "0"
//---later in Uart0_Rx_Handler()---
rxByte = U0RXREG; //rxByte set to (for example) 55
//---later in main()---
printf("%d", rxByte); //still prints "0"!!!
If a variable is modified by an interrupt handler, it needs to be declared volatile. Volatile lets the compiler know that the variable could be modified asynchronously and that it shouldn't used a cached copy in a register.
//---in main()---
volatile unint8_t rxByte = 0;
printf("%d", rxByte); //prints "0"
//---later in Uart0_Rx_Handler()---
rxByte = U0RXREG; //rxByte set to 55
//---later in main()---
printf("%d", rxByte); //corectly prints 55
Overrunning an array's bounds
There are no checks in C to prevent you from going beyond the bounds of an array.
int array[10];
int my_var = 55;
printf("%d", my_var); //prints "55"
for(i=0; i<11; i++) // eleven is one too many indexes for this array
{
array[i] = i;
}
printf("%d", my_var); // prints "11"!!!
In this case, we go through the loop 11 times, which is one index bigger than the array. In most compilers, this will result in overwriting variables declared after the array (anywhere on the page, they don't even have to be declared on the next line). This scenario can occur in many different circumstances, including multi-dimensional arrays and stack corruption.
Forgetting to dereference a pointer
While trivial, forgetting the asterisk on a pointer when making assignments will not set the variable correctly
int* pCount;
pCount = 10; //forgot the asterisk!!!
printf("%d", *pCount); //prints ??
Masking a variable with the same name
Reusing a variable name in an inner scope (like inside an if/for/while block or inside a function) hides a variable with the same name elsewhere.
int count = 10; //count is 10
if(byteRecevied)
{
int count = U0RXREG; //count redeclared!!!
DoSomething(count);
printf("%d", count); //prints "55"
}
printf("%d", count); //prints "10"
I'd like to add another possible reason to Zack's excellent answer.
Optimisation
This one frequently surprises me. A good optimising compiler will notice when two different variables are never used at the same time, and will optimise the program by giving those variables the same address in memory. When you are stepping through the code, you may see a variable apparently changing in the watch window. But what's really happening is that the variable that shares its address is being written to.
The other trick the compiler pulls is simply getting rid of a variable that it realises isn't necessary. Sometimes you might be doing the equivalent of this in your code:
force_a = mass_a * acceleration_a
force_b = mass_b * acceleration_b
total_force = force_a + force_b
The compiler sees that there's no real need for the variables force_a and force_b, and so changes the code to this:
total_force = (mass_a * acceleration_a) + (mass_b * acceleration_b)
You'll never see force_a and force_b being updates, but you'll still be able to add them to the watch window.
When I step through my program, I'm convinced that some variable or other has the wrong value in it, but when I let my program run through without stepping, it seems to work. Check that this isn't happening to you.
Added:
As Ashish Kulkarni mentioned, you can check this by turning off optimisation.

On understanding how printf("%d\n", ( { int n; scanf("%d", &n); n*n; } )); works in C

I came across this program via a quora answer
#include<stdio.h>
int main() {
printf("%d\n", ( { int n; scanf("%d", &n); n*n; } ));
return 0;
}
I was wondering how does this work and if this conforms the standard?
This code is using a "GNU C" feature called statement-expressions, whereby a parentheses-enclosed compound statement can be used as an expression, whose type and value match the result of the last statement in the compound statement. This is not syntactically valid C, but a GCC feature (also adopted by some other compilers) that was added presumably because it was deemed important for writing macros which do not evaluate their arguments more than once.
You should be aware of what it is and what it does in case you encounter it in code you have to read, but I would avoid using it yourself. It's confusing, unnecessary, and non-standard. The same thing can almost always be achieved portably with static inline functions.
I don't believe it does work... n has local scope within the braces... when you exit the braces, n becomes undefined though I suppose is could still exist somewhere on the stack and might work. It's begging for implementation issues and I guarantee is implementation dependent.
One thing I can tell you is that anyone working for me who wrote that would be read the riot act.
It works. I get no warnings from gcc, so I suppose that it conforms to the standard.
The magic is the closure:
{ int n; scanf("%d", &n); n*n; }
This nugget scans an integer from the console (with no error checking) and squares it, returning the squared number. In ancient implementations of C, the last number on the stack is returned. The n*n puts the number on the stack.
That value gets passed to the printf:
printf("%d\n", <scanned>);
So, to answer your questions: Yes, it works. Yes, it's "standard" (to the extent that anyone follows the standard entirely). No, it's not a great practice. This is a good example of what I by knee-jerk reaction call a "compiler love letter", designed mostly to show how smart the programmer is, not necessarily to solve a problem or be efficient.

Resources