Below is a code which I am not understand.
#include<stdio.h>
int main(int argc, char *argv[])
{
int num;
printf("\n Number: " );
scanf("%d", &num);
if (num >= 0)
{
int abs = num;
}
else
{
int abs = -num;
}
{
int abs;
printf("\n Values are %d %d", num ,abs);
}
return 0;
}
When I enter a number as 4, the output is Values are 4 4
When I enter a number as -4, the output is Values are -4 4
I am not able to understand how is it able to print the absolute value?. the variable abs defined in the if loop and else loop should have been deallocated after exiting.
Kindly let me know.
Regards,
darkie
You are absolutely correct.
Do you see the last block where int abs is declared that last time? Notice that abs is not initialized, and using uninitialized variables yields undefined results. With your particular compiler, it just happens that you luck out, and block of memory where the new abs sits still contains the result from it's (expired) previous scope.
These variables are allocated on the stack yet you didn't modify it, I mean you didn't get out of the function, so yet, programmatically you'll get a "new" 'abs' int in the last code block, but in reality, this "new" 'abs' int is in the place where the old 'abs' was (on the STACK!), thus, its default value is the same.
That's called "undefined behavior".
You're getting "stack trash" when you declare the abs with the printf.
It works like this:
if (num >= 0) {
create 'abs' at memory address N, put 'num' in it.
destroy 'abs' // but leave the 'garbage' at memory address N
} else {
create 'abs' at memory address N, put '-num' in it.
destroy 'abs' // but leave the 'garbage' at memory address N
}
{
create 'abs' at memory address N, don't put anything in it.
// your compiler has decided it will reuse N. That's a valid choice.
// your compiler has decided it will not zero the memory at address N. That's valid.
read whatever was at 'abs'. // it's whatever was assigned in the conditional.
}
Always compile with -Wall :)
Hilarious code.
It relies on the fact that all three definitions of abs will be allocated on the same place on the stack, due to compiler optimization.
The third abs has to be random garbag, the garbage turns out to be the result of the previous variable with the same name (the name would not matter).
You're using an uninitialized value of abs in the printf. The C language standard doesn't require it to be anything in particular because it's uninitialized. It could be 0, or 1, or -32765
In this particular case, you're probably getting the same number because the compiled code is reusing a register for the temporary values of abs, and that same register again for your abs variable in the printf block.
You can look at the disassembly code to see exactly what the compiler is doing in terms of machine instructions.
Related
I'm fairly new to coding and am currently learning C. In my C programming class, my instructor gave us the assignment of writing a program that uses a function which inputs five integers and prints the largest. The program is fairly simple even for me, but I'm facing some problems and was hoping to get some advice.
#include <stdio.h>
int largest(int x);
int main(void) {
int integer1;
largest(integer1);
return 0;
}
int largest(int x) {
int i;
for (i = 0; i < 5; i++) {
printf("Enter an integer: ");
scanf_s("%d", &x);
}
return x;
}
This is the code that I have written. The main problem that I am having is that in my main method, the IDE tells me to initialize the value of integer1. However, I'm not really sure how to do that because I'm supposed to input the value within the largest() method via the scanf_s function. How may I solve this?
The problem is here, the warning message is to warn you about the potential pitfall of using the value of an uninitialized automatic local variable. You made the call like
largest(integer1);
but you ignore the return value, so the integer1 remains uninitialized.
Remember, in view of largest(), x is a local copy of the actual argument passed to that function, any changes made to x won't be reflecting to the caller.
That said, your code is nowhere near your requirement, sorry to say. A brief idea to get there would be
Create a function.
Create a variable (say, result) and initialize with minimum possible integer value, INT_MIN
Loop over 5 times, take user input, compare to the result value, if entered value found greater, store that into result, continue otherwise.
return result.
I know that normally help for assignments shouldn't be given but I have to say that you might need to rethink what you want to do.
You are inputting an integer to the function named largest. But why are you only inputting a single integer to a function that should return the largest value. You can't do much with a single number in that case.
You should instead be inputting say an array of 5 values(as said in your assignment) to the function and let it return the largest.
The order would then be:
Read 5 values and save to an array
Call the function largest with the array as input
Let the function do it's work and return the largest value
Do what ever you want with the largest value
But if you only want to remove the warning simply type
int integer1 = 0;
In C99, is there a big different between these two?:
int main() {
int n , m;
scanf("%d %d", &n, &m);
int X[n][m];
X[n-1][m-1] = 5;
printf("%d", X[n-1][m-1]);
}
and:
int main(int argc, char *argv[]) {
int n , m;
int X[n][m];
scanf("%d %d", &n, &m);
X[n-1][m-1] = 5;
printf("%d", X[n-1][m-1]);
}
The first one seems to always work, whereas the second one appears to work for most inputs, but gives a segfault for the inputs 5 5 and 6 6 and returns a different value than 5 for the input 9 9. So do you need to make sure to get the values before declaring them with variable length arrays or is there something else going on here?
When the second one works, it's pure chance. The fact that it ever works proves that, thankfully, compilers can't yet make demons fly out of your nose.
Declaring a variable doesn't necessarily initialize it. int n, m; leaves both n and m with undefined values in this case, and attempting to access those values is undefined behavior. If the raw binary data in the memory those point to happen to be interpreted into a value larger than the values entered for n and m -- which is very, very far from guaranteed -- then your code will work; if not, it won't. Your compiler could also have made this segfault, or made it melt your CPU; it's undefined behavior, so anything can happen.
For example, let's say that the area of memory that the compiler dedicates to n happened to contain the number 10589231, and m got 14. If you then entered an n of 12 and an m of 6, you're golden -- the array happens to be big enough. On the other hand, if n got 4 and m got 2, then your code will look past the end of the array, and you'll get undefined behavior -- which might not even break, since it's entirely possible that the bits stored in four-byte segments after the end of the array are both accessible to your program and valid integers according to your compiler/the C standard. In addition, it's possible for n and m to end up with negative values, which leads to... weird stuff. Probably.
Of course, this is all fluff and speculation depending on the compiler, OS, time of day, and phase of the moon,1 and you can't rely on any numbers happening to be initialized to the right ones.
With the first one, on the other hand, you're assigning the values through scanf, so (assuming it doesn't error) (and the entered numbers aren't negative) (or zero) you're going to have valid indices, because the array is guaranteed to be big enough because the variables are initialized properly.
Just to be clear, even though variables are required to be zero-initialized under some circumstances doesn't mean you should rely on that behavior. You should always explicitly give variables a default value, or initialize them as soon as possible after their declaration (in the case of using something like scanf). This makes your code clearer, and prevents people from wondering if you're relying on this type of UB.
1: Source: Ryan Bemrose, in chat
int X[n][m]; means to declare an array whose dimensions are the values that n and m currently have. C code doesn't look into the future; statements and declarations are executed in the order they are encountered.
In your second code you did not give n or m values, so this is undefined behaviour which means that anything may happen.
Here is another example of sequential execution:
int x = 5;
printf("%d\n", x);
x = 7;
This will print 5, not 7.
The second one should produce bugs because n and m are initialized with pretty much random values if they're local variables. If they're global, they'll be with value 0.
I ran the following code and this is the output I got:
#include <stdio.h>
int main()
{
int x = 3;
int y = x;
printf("%d\n", &x);
printf("%d\n", &y);
getchar();
return 0;
}
Output:
3078020
3078008
Now, the output changes every time I run the program, but the difference between the location of x to the location of y is always 12. I wondered why.
Edit: I understand why the difference is constant. What I don't understand is why the difference is specifically 12, and why the memory address of y, who's defined later, is less than x's.
The addresses themselves may well change due to protective measures such as address space layout randomisation (ASLR).
This is something done to mitigate the possibility of an attack vector on code. If it always loads at the same address, it's more likely that a successful attack can be made.
By moving the addresses around each time it loads, it becomes much more difficult for an attack to work everywhere (or anywhere, really).
However, the fact that both variables will be on the stack in a single stack frame (assuming the implementation even uses a stack which is by no means guaranteed), the difference between them will be very unlikely to change.
In your code,
printf("%d\n", &x);
is not the correct way to print a pointer value. What you need is
printf("%p\n", (void *)&x);
That said, the difference between the addresses is constant because those two variables are usually placed in successive memory locations in stack. However, AFAIK this is not guranteed in c standard. Only thing guraneted is sizeof(a) [size of a datatype] will be fixed for a particular platform.
To print the address of a variable you have to use the %p not %d.
To print the integer value only you have to give %d.
printf("%d\n",x);// It will print the value of x
printf("%p\n",(void*)&x);// It will print the address of x.
From the man page of printf
p The void * pointer argument is printed in hexadecimal
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 found some code and I am baffled as to how the loop exits, and how it works. Does the program produce a deterministic output?
The reason I am baffled is:
1. `someArray` is of size 2, but clearly, the loop goes till size 3,
2. The value is deterministic and it always exits `someNumber` reaches 4
Can someone please explain how this is happening?
The code was not printing correctly when I put angle brackets <> around include's library names.
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
int main() {
int someNumber = 97;
int someArray[2] = {0,1};
int findTheValue;
for (findTheValue=0; (someNumber -= someArray[findTheValue]) >0; findTheValue++) {
}
printf("The crazy value is %d", findTheValue);
return EXIT_SUCCESS;
}
Accessing an array element beyond its bounds is undefined behavior. That is, the program is allowed to do anything it pleases, reply 42, eat your hard disk or spend all your money. Said in other words what is happening in such cases is entirely platform dependent. It may look "deterministic" but this is just because you are lucky, and also probably because you are only reading from that place and not writing to it.
This kind of code is just bad. Don't do that.
Depending on your compiler, someArray[2] is a pointer to findTheValue!
Because these variables are declared one-after-another, it's entirely possible that they would be positioned consecutively in memory (I believe on the stack). C doesn't really do any memory management or errorchecking, so someArray[2] just means the memory at someArray[0] + 2 * sizeof(int).
So when findTheValue is 0, we subtract, then when findTheValue is 1, we subtract 1. When findTheValue is 2, we subtract someNumber (which is now 94) and exit.
This behavior is by no means guaranteed. Don't rely on it!
EDIT: It is probably more likely that someArray[2] just points to garbage (unspecified) values in your RAM. These values are likely more than 93 and will cause the loop to exit.
EDIT2: Or maybe someArray[2] and someArray[3] are large negative numbers, and subtracting both causes someNumber to roll over to negative.
The loop exits because (someNumber -= someArray[findTheValue]) doesnt set.
Adding a debug line, you can see
value 0 number 97 array 0
value 1 number 96 array 1
value 2 number 1208148276 array -1208148180
that is printing out findTheValue, someNumber, someArray[findTheValue]
Its not the answer I would have expected at first glance.
Checking addresses:
printf("&someNumber = %p\n", &someNumber);
printf("&someArray[0] = %p\n", &someArray[0]);
printf("&someArray[1] = %p\n", &someArray[1]);
printf("&findTheValue = %p\n", &findTheValue);
gave this output:
&someNumber = 0xbfc78e5c
&someArray[0] = 0xbfc78e50
&someArray[1] = 0xbfc78e54
&findTheValue = 0xbfc78e58
It seems that for some reason the compiler puts the array in the beginning of the stack area, then the variables that are declared below and then those that are above in the order they are declared. So someArray[3] effectively points at someNumber.
I really do not know the reason, but I tried gcc on Ubuntu 32 bit and Visual Studio with and without optimisation and the results were always similar.