I am taking a course where we were doing a lot with systems level programming, and now we are getting to the point where we are starting the introduction to C. We are given some code and told to state the values printed out by each 'printf' statement. I know how to do regular printing statements in languages like Java and Python. But the code given has bodies to the print sections which I have not seen before. The statements are executed in the order A, B, C, D. Here is the code:
int t; /* This variable is global */
{
int t = 2;
printf("%d\n", t); /* A */
{
printf("%d\n", t); /* B */
t = 3;
}
printf("%d\n", t); /* C */
}
{
printf("%d\n", t); /* D */
}
The part that confuses me is that some of the print statements have bodies. A print statement inside a print statement?
So here is what I am thinking: t = 2 so when we get to A, it executes the body within A first. So the first statement in that body is to print t which at this point is 2. Then after we print 2, we change the value in t to 3. After that we go to C which just prints t which is 3 (I guess? I'm not sure here). After that we go to the body that contains D. Int t is a global variable declared above, but it is never initialized (except in the first portion of code). So in the second portion that contains D, would there be an error since t is not initialized in that block of code?
2
3
3
Error
I feel like I am wrong.
First, you have a global variable t, which is initialized to 0 (AFAIK, all global variables in C are initialized to 0 if not explicity initialized)
Then, a block is opened and a local variable t is declared and initialized to 2, which shadows the global variable with the same name (in java this is an error, the compiler will complain and refuse to use the same name), for the whole block.
The first printf, which is inside the block, prints 2.
Then a nested block opens, with a printf in it. This printf will also use the local variable t, printing 2 again.
Then t is assigned 3. This "t" cannot be other than the local variable.
Then, the nested block closes and we are back into the first still opened block in which local t was declared. The printf here prints 3.
Then the first block finishes and so the local variable t is gone. A new block opens and the last printf prints the value of global variable t, which is the only one known in this block. It prints 0.
The curly braces begin and end new scopes, just like they do with functions.
There are two "main blocks" in your program. One contains a definition of variable t, thus shadowing the global t. Therefore 2, 2, and 3 is printed out. The second block can access the global t, so the printf in the second block prints out the value of the global t.
Global variables are initialized to 0 by default, so the last printf call prints 0 to the screen.
Local variables are not initialized with any value, so the last printf call would yield undefined behavior.
The output is
2
2
3
and after that
0
if the "global" t really is global or (probably1) some random value if it is local.
1 Undefined behavior occurs. Anything may happen. In this case, it's probably a random value getting printed out.
Related
I've seen a C program that prints 1 to 1000 without using any looping structure or conditional statements, but I don't understand how it works. Can anyone go through the code and explain each line?
See live demo here. Why does it result in a runtime error?
#include <stdio.h>
#include <stdlib.h>
int main(int i)
{
printf("%d\n",i);
((void(*[])()){main, exit})[i / 1000](i + 1);
return 0;
}
((void(*[])()){main, exit})[i / 1000](i + 1);
This line create a two-element array of function pointers, with the first element containing the main function, and other element containing the exit function.
It then indexes this array by i / 1000. This either gets the main function if i < 1000 or the exit function when i == 1000.
It then calls the function pointer that it just indexed with i+1 as the argument.
It's a recursive function, with the stopping condition determined with an array index rather than a conditional. I don't think it's valid C however; main's signature is wrong, and the cast to a function pointer removes the return type from the main function.
Breaking down the line that you asked about
((void(*[])()){main, exit})
This is an array literal, which creates an unnamed temp array of two function pointers, and initializes those pointers to point at main and exit
[i / 1000]
This indexes that temp array. Integer division truncates towards 0, so when 0 <= i < 1000, this gets element 0 (the pointer to main) and when 1000 <= i < 1999, it gets element 1 (the pointer to exit)
(i + 1);
This calls the pointed at function with i+1 as an argument.
There are a bunch of things here that are undefined behavior. Declaring main as having a single int argument is illegal according to the standard, though generally will work, getting the number of command line arguments as the single argument. Getting a pointer to main is likewise undefined, as main is a special function that may have a non-standard calling convention.
This code is a good example of how far you can bend C without breaking it. You shouldn't attempt to understand this until you can write understandable C.
Here are the key features and assumptions:
First, assume that the program is called without arguments. The parameter i is in the place usually called argc, so it will have the initial value 1 (the number of elements in the array of arguments, usually called argv).
Next, assume that the single-argument form of main doesn't cause any problems. Officially supported forms of main are with no arguments, 2 arguments (argc, argv), and sometimes 3 arguments (argc, argv, envp).
So the first printf prints 1.
Next we have a compound literal. It might be easier to understand if you look at a simpler one first:
(int[]){10,20}
That's an anonymous array of 2 ints, with values 10 and 20. int[] is the type. It goes in parentheses before a braced list of values. So what's this:
(void(*[])()){main, exit}
void(*[])() is a type. It means array of function pointers with the signature void (*foo)(). The type name in parentheses followed by a braced list is compound literal, just like the (int[]){10,20} example. In this case, it creates an array of 2 function pointers whose elements are main and exit.
Assume that the mismatch between the function pointer type (returns void) and main (returns int) doesn't cause a problem.
This:
((void(*[])()){main, exit})[i / 1000]
is our anonymous array of 2 elements, inside some redundant parentheses, followed by [i / 1000]. That's just normal array indexing syntax. If i/1000 is 0, you get the first element of the array (thearray[0]), which is main. That happens for all i is between 0 and 999. If i/1000 is 1, which happens when i==1000, we're looking at thearray[1], which gets us the second element: exit.
So far, we have an expression taht is equal to main when i<1000 and equal to exit when i==1000.
Now look at the whole statement:
...that_big_thing_that_is_either_main_or_exit...(i + 1)
A function pointer, followed by a parenthesized argument list. That's a function call. Whichever function we chose from the array, now we're going to call it, providing an argument that is equal to the incoming argument (i) plus 1.
So the first call, when i is 1, selects main for the function and i+1 = 1+1 = 2 for the argument. It calls main(2).
main(2) does a printf which prints the 2, and then calls main(3).
main(3) does a printf which prints the 3, and then calls main(4).
...and so on until...
main(999) does a printf which prints the 999, and then calls main(1000).
main(1000) does a printf which prints the 1000, and then calls exit(1001).
None of the calls to main ever return, and the return 0 never happens, because the exit terminates the process. The fact that the process returns an exit code of 1001 rather than 0 appears to be the reason for ideone's "runtime error" message.
The main function is called recursively.
void print_nb(int n)
{
if (n <= 1000)
{
printf("%d\n", n);
print_nb(n + 1);
}
}
Like Sourav Ghosh said, it's prohibited to use with main() recursively, better use another function.
Good evening guys,
This is a little program shown below. I'm seeking for garbage value of b in every execution, but get the same answer.
The code is simple as follows:
#include<stdio.h>
#include<conio.h>
int main(void)
{
int a = 300, b,c;
if (a>=400)
b=300;
c=200;
printf("\n%d\n%d",b,c);
getch();
}
The o/p in Codeblocks is as follow
2
200
but if I remove the line
b=300;
keeping the semicolon, then it gives garbage values.
Why is this contradiction happening?
Reading uninitialized variable follow below rules,
Static variable are by default initialized to zero means local static or file scope variable (global one).
Non-static variables which local to function are indeterminate. Reading them prior to assigning a value results in undefined behavior. compiler is free to do any thing. It can be zero, it can be the value that was in there, it can crash the program. you have absolutely no guarantees.
It will simply give you the last value that was stored in that position on the stack (or in that register if the variable happens to be stored in a register).
Also undefined might be different between different compilers.
Here 2 is garbage only, you should print the value of b before 'if-statement' and see if it matches with the last print statement. If it matches then both are garbage values and no change occurred to them because of the 'if-statement'.
The question about how compiler generates a garbage value is unpredictable/random.
Explanation:
Step 1: int a = 300, b, c; here variable a is initialized to '300', variable b and c are declared, but not initialized.
Step 2: if(a >= 400) means if(300 >= 400). Hence this condition will be failed.
Step 3: c = 200; here variable c is initialized to '200'.
Step 4: printf("%d, %d, %d\n", a, b, c); It prints "300, garbage value, 200". because variable b is not initialized.
I'm very new to C, and am writing a few programs to try and understand how variables can be passed and changed in between functions. I wrote a simple program below:
int number;
int test( int number ) {
number = 3;
return(number);
}
int main () {
printf ("\nPlease enter in any number between (10 - 99,999)!\n");
scanf("%d", &number);
test(number);
printf ("\nYour number probably wasn't: %d\n", number);
}
The point was to enter in a number, but no matter what you enter that number would be changed to 3. For some reason though when i call test on that number, it will not change to 3 but instead be whatever the user entered. Note that I am trying to change the variable number, and not have any other variable hardcoded as 3.
How come this does not work?
Change
test(number);
to
number = test(number);
Otherwise the value returned by test will be discarded and you will get the number you entered, not 3.
Another way to get the desired effect is to pass the pointer to number:
void test( int *number ){..}
and call the function as
test(&number);
Some answers suggested that to use number as global variable. I advice you that do not use global variable when it is unnecessary.
You are changing a local variable in the function test, not the actual variable. You want number = test(number); as the second to last line in your main() function.
Your function test doesn't deal with the original number that you passed to it. Instead, it gets a copy of this variable and plays around with it locally. Any changes you make to number in this function will get lost (unless you pass in a reference, which you will learn about later, presumably). The correct way to get around this is, as you have already done, return the value of number. However, you don't use that returned value at all. When you say number = test(number);, you are telling the computer to take that returned value and assign it to the original number (the one in your main), which is what you want.
int number; //a
int test( int number ) { //b
number = 3;
return(number);
}
Within test, there are actually two variables named number,
a (which is the number used in main too), and b which has priority.
You´re changing the parameter b to 3.
However, the parameter is only a copy of the original passed value in main
(as usual in C and C++), and gets discarded and the end of test.
Furthermore, you´re not using the return value in main, so 3 is gone.
Perhaps you misunderstand the idea of 'variable scope'.
int number;
The first occurrence of the variable 'number' is declared outside of all functions (and braces). Hence, it has "global" scope.
int test( int number ) {
The variable 'number' defined as an argument to test() has a limited scope. Its life, and visibility, is limited to the braces of the test() function. Outside these braces, this 'number' variable does not exist.
The 'global' variable 'number' and the 'test()' variable 'number' are distinct from each other, each with its own unique value.
Being they are named the same, the 'global' variable 'number' becomes inaccessible inside the 'test()' braces. Hence, any manipulation of the 'number' within the braces of 'test()' does not have any effect on the 'global' variable 'number'.
number = 3;
The above has no effect on the 'global' variable 'number'. Rather it only initializes the 'local' variable 'number' to 3.
return(number);
The above will return the value of the 'local' variable 'number' (3).
}
int main () {
printf ("\nPlease enter in any number between (10 - 99,999)!\n");
scanf("%d", &number);
The line above sets the 'global' variable 'number' to a value entered by the user.
test(number);
The line above passes the value of the 'global' variable 'number' to test. It does not capture the 'return' value (3) returned by test. If desired, the above line could be rewritten:
number=test(number);
The above line would set the 'global' variable 'number' to the return value of test (3).
printf ("\nYour number probably wasn't: %d\n", number);
}
All answers so far seem to ignore the fact that you are trying something which does not make much sense. You are returning what is basically a constant from your function, but using a passed value as some intermediate storage while that is completely unnecessary. Either of those two will work:
void test( int& number ) {//We don't need to return anything, because we pass number by reference, and so changes made to it will persist outside this functions scope
number = 3;
}
int test(){
return 3; //We just return 3, we don't need any arguments passed to the functions in this version
}
Now in the first case you call the functions as
test(number); //number will be changed by test because it's passed by reference
in the second case you call the functions as
number = test(); //Here test just returns 3 and we assign that value to number.
Edit:
Just for completeness sake I will add the third version that you can use:
void test(int* number){//Here we pass a pointer to an integer to test
*number = 3;//and change the value pointed to be number to 3. Read * as 'value pointed at by'. So this says 'value pointed at by number = 3'
}
in this case you call the function as
test(&number)//read & as 'pointer to'. So now we pass 'pointer to a' to test.
Note that this version is basically a less elegant and more error prone version of the first version I mentioned (at least in this specific scenario). Their usage and effects are more or less equal, but in the first version you do not need to concern yourself with dereferencing and the general fact that you are working with pointers.
Your code never does anything with the value test returns. Your code would be easier to understand if you didn't call both variables (the one in main and the one in test) number.
You have 2 options. One is
number = test(number);
Second is refer Pointers in C. Pass by address would do the trick for you.
It doesn't work because you're doing a pass by value instead of a pass by reference. If you want the value of number to be always 3 without doing an assign when you call the function, then you should do something like:
void test(int *number){
*number = 3;
}
and call like:
test(&number);
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.
#include<stdio.h>
int main(void) {
int a = 123,b,c;
if(a>300) {
b=200;
}
c=4556;
printf("b = %d\n",b);
return 0;
}
Now as if block evaluates to false so if block should not get executed, but the code is printing value of b as 0.
Moreover if the value of c isn't assigned after the if block is over then the code shows some garbage value for b.
Can anyone tell me why is this happening like this, as far as I know b must show some garbage value for the first case also.
Unless you initialise your variables, you will not know for sure what their values are so this is not remotely surprising. If you want your b variable to contain a meaningful value, then initialise it with that value.