Variable being used without being initialized? C Language - c

I can't quite figure out what my issue is here. I keep getting an error in my code.
Error: Run-Time Check Failure: Variable used without being initialized.
: warning C4700: uninitialized local variable 'b' used
can someone help me solve this problem ? Any help would be appreciated.I'm using visual studio as a compiler for C and I'm a beginner in it and this is a one of the assignment. I don't see why i keep getting this issue if i input "int b;" in the beginning of the program. Wouldn't that variable be initialized?
Here is the code:
#include <stdio.h>
//Create a program that asks the user to enter a number until the user enters a -1 to stop
int main()
{
int b;
//as long as the number is not -1, print the number on the screen
while(b!=-1) {
printf("Hello there! would you please enter a number?");
scanf(" %d",&b);
//as long as the number is not -1, print the number on the screen
if(b!=-1){
printf("Thank you for your time and consideration but the following %d you entered wasn't quite what we expected. Can you please enter another?\n",b);
//When the user enters a -1 print the message “Have a Nice Day :)” and end the program
}else {
printf("Have a Nice Day :), and see you soon\n");
}
}
return 0;
}

When you declare a variable, such as you have:
int b;
It is not initialised to have any value, it's value is unknown until you initialise it.
To fix this error, replace
int b;
With
int b = 0;

Error is here:
int main()
{
int b;
//as long as the number is not -1, print the number on the screen
while(b!=-1) {
Since you haven't initialized b, it can be anything. You then use it as a condition for while loop. This is very dangerous.
It may be that system randomly assign value of -1 ( its a rare possibility ) to it .. in that case your while loop will not be actioned
Intialize b to some value
For eg do this:
int b = 0;

You're doing:
int b;
and then doing:
while(b!=-1) {
without ever initializing b. The problem is exactly what your warning is telling you it is.
C does not automatically initialize local variables for you, the programmer has to take care of that. int b allocates memory for your variable, but doesn't put a value in there, and it will contain whatever garbage value was in that memory prior to allocation. Your variable won't be initialized until you explicit assign, or another function explicitly assigns, a value to it.

int b;
is a variable declaration. Explicitly, the value is not initialized. The compiler will emit instructions for the program to reserve space to store an integer at a later time.
int b = 1;
this is a variable declaration with initialization.
int b;
while (b != -1)
this is use of an uninitialized variable, but so is
int a = rand() % 3; // so 'a' can be 0, 1 and or 2.
int b;
if (a == 0)
b = 1;
else if (a == 1)
b = 2;
printf("b = %d\n", b);
this is also a potential cause of uninitialized use of b. If 'a' is 2, we never assign a default value to b.
Upshot is you should always try to specify the default value with the declaration. If the logic that will determine initialization is complex, consider using an out-of-bounds value, as you are using -1.
Can you spot the bug in the following?
int b = -1;
if (a == 0)
b = 1;
else if (a == 1)
b = 2;
else if (a > 2)
b = 3;
if (b == -1) {
// this is an error, handle it.
}

Related

Why does declaring variables on a single line give an unexpected result?

I programmed a simple clock and found that while hours and seconds are okay, minutes are not if I declare the variables on a single line (minutes starts at 16 and not at 0 as expected).
The problem is solved if I declare the variables on separated lines. I'm still curious though, anybody knows why?
Here's the code:
#include <stdio.h>
#include <windows.h>
//h=hours, m=minutes, s=seconds.
int main(){
int h, m, s = 0; //THIS IS THE LINE: WHY "m" STARTS AT 16 AND NOT 0?
int delay = 1000;
while(1){
s++;
if(s>59){
m++;
s=0;
}
if(m>59){
h++;
m=0;
}
if(h>12){
h=1;
}
printf("\n %02d:%02d:%02d", h, m, s);
Sleep(delay);
system("cls");
}
}
Your variables are uninitialized - they can take any value, and using them before initialization is (usually) indeterminate behavior.
A line of code like:
int h, m, s = 0;
does not define each variable to be zero - only the third one. It is equivalent to:
int h;
int m;
int s = 0;
To fix, initialize all of your variables as zero:
int h = 0, m = 0, s = 0;
You haven’t initialized h or m, so their initial values might whatever was in that memory already, or something else entirely. C does not automatically initialize variables to 0.
When you declare multiple variables on one line, the value only applies to the variable it comes after. So
int a, b, c = 5;
only sets c to 5, while
int a = 1, b = 2, c = 3;
initializes all of them. In your case, you just need to use
int h = 0, m = 0, s = 0;
You compiler likely has an option for warnings (-Wall in gcc), which should warn you about using an uninitialized variable.
int h, m, s = 0; // THIS IS THE LINE: WHY "m" STARTS AT 16 AND NOT 0?
Well, I guess, because C is not English. The "= 0" part applies just to that one variable name s, not to the whole line.
Although, you know, English doesn't necessarily apply modifiers to the whole line, either. If I say "There were three people standing on the streetcorner: A man, a woman, and a boy named Brad", you would not infer that the man and the woman were named Brad, too, would you?
[Footnote: Now I've got that old song "Me and you and a dog named Boo" stuck in my head. :-) ]

How do you differentiate between zero and not-initialised in C?

How do you check if a value is zero or has not been given?
int points[3];
points[0]=1;
points[1]=0;
for(int i=0;i<sizeof(points)/sizeof(*points);i++){
if(points[i]&&points>0){printf("Value is %d \n",points[i]);}
else if(!points[i]){printf("Value is zero \n");}
else{printf("Not set/provided\n");} // catching points[2]
}
Here, how do you differentiate between points[1] and points[2]?
"How do you differentiate between zero and not-set" and "how do you differentiate between points[1] and points[2]" implies a misunderstanding. points[2] in this case is not initialized nor assigned. It is not specified to be any legitimate value.
if(points[i] ... is UB when i==2.
Assign points[2] before reading it.
How do you differentiate between zero and not-initialised in C?
Code does so by keeping track of elements initialized or assigned prior. In this case, only points[0], points[1] has been assigned. Code does not attempt to differentiate by reading points[i].
A common idiom is to first zero fill the entire object:
int points[3] = { 0 };
There is no general way without initialization.
In some cases such as debug mode in vs, they will be initialized with zero, but in generally, c or c++ engine will set random values to non-initialized variables.
You have to do as follows:
int points[3] = {1, 0, -1};
for (int i = 0; i < 3; i++)
{
if (points[i] > 0) printf("value: %d", points[i]);
else if (points[i] == 0) printf("value is zero");
else printf("value is not setted.");
}
C does not have any feature to find uninitialized value. If the uninitialized variable is static or global, its value will be always 0, else it could be anything in the range of the type of variable. What you can do is assign a sentinel value as an indicator.
For example, if you are certain that the value of the variable will always be positive then you can assign a negative number to keep track, if the variable is ever changed or not

type conversion data printing Error in C lang

In C
int n=100;
printf("%d", (int)(sqrt((double)n)));
When I use this code it prints the correct answer (10).
But following code always prints 0
int n;
int max = (int)(sqrt((double)n));
printf("%d", max);
Why are the answers are different ?
int n=100;
printf("%d", (int)(sqrt((double)n)));
In this case, the value of n is known i.e, 100. So sqrt((double)n) returns the correct value.
int n;
int max = (int)(sqrt((double)n));
printf("%d", max);
Here, the variable n is uninitialized. The variable could be holding an indeterminate value depending upon whether it is declared locally (inside a block, in which case the value of n would be a junk value) or globally (outside a block, in which case the value of n would be zero). Always initialize your variables to avoid such errors.

How is atomic_dec_if_positive atomic?

So I am reading atomic.h from Linux source code from here (found it on google. I am not sure if it's legit) and I just can't wrap my mind around this:
how is this atomic?
static inline int atomic_dec_if_positive(atomic_t *v)
{
int c, old, dec;
c = atomic_read(v);
for (;;) {
dec = c - 1;
if (unlikely(dec < 0))
break;
old = atomic_cmpxchg((v), c, dec);
if (likely(old == c))
break;
c = old;
}
return dec;
}
It uses the functions atomic_read() and atomic_cmpxchg(), which surely somewhere will be implemented in assembly language using atomicity features of the microprocessor's instruction set.
It first reads a value and makes sure it is positive, stores the read value in c, the decremented value in dec and calls atomic_cmpxchg() which will atomically do the following: "write dec in *v only if the value in *v is equal to c, and return the old value in *v". That way you make sure that the value in *v was not changed between the two atomic calls. If it fails and the return value was different from the expected contents of *v, it retries the whole process.
The following line
c = atomic_read(v);
means at this point in time we know the value of the atomic_v variable == c. We
decrement c to give us our required value.
dec = c - 1;
Obviously if the number is not positive and 0 is not positive we cannot
decrement it.
if (unlikely(dec < 0))
break;
Now we try and change our known old result with the expected result
old = atomic_cmpxchg((v), c, dec);
This is defined as
int atomic_cmpxchg(atomic_t *v, int old, int new);
If we write it out as follows and assume that the whole function is atomic. We have
int atomic_cmpxchg(atomic_t *v, int old, int new) {
&v->counter = &v->counter == old ? new : old;
return old;
}
Note, I'm treating v as an integer, on x86 it's a struct. At this point we
know that at the point of the the atomic operation happening we get the
old value. Our expected old value is c, so if this is the case then we have
successfully decremented the value, return the result.
if (likely(old == c))
break;
If not we need to reset our expectataion ie our start point, we're decrementing a new value c not the old one we had when last entered the for(;;) loop
c = old;
The important part here is that this is in a loop, this loop will continue until it succeeds to decrement the value or the value is non positive.

Initializing int Array in C Without Assigning Values

I'm working through K&R exercise 1-13, and I forgot to set the elements in my array to 0. To my surprise, the last value that I got when printing the array was 32767; subsequent tests have different element values for the array, some different, and some not.
I'd like to know why this is happening. If it's highly complex, then what's going on in simple terms?
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* print the length of words as input to a histogram with horizontal bars */
int main() {
int c, i;
int state = OUT;
int accum = 0;
int nchar[10];
while ((c = getchar()) != EOF) {
if (c != ' ' && c != '\n' && c != '\t') {
state = IN;
++accum;
}
else {
state = OUT;
++nchar[accum];
accum = 0;
}
}
for (i = 0; i < 10; ++i)
printf("%d\n", nchar[i]);
return 0;
}
Input & Corresponding Output:
hello codes
4195584
0
0
0
4196032
2
4195584
0
-1608045280
32767
When the array is created, the compiler claims memory on the stack. Data is written to that memory location, if you are initializing the array or (in general) assigning values to it.
If you do not initialize anything, just memory is claimed, which was already used before for something else. The stack is not zeroed after data gets removed, because it would waste too much processor time and the RAM is getting filled with data again anyway.
That's simply what happens when you don't initialize your memory. You get whatever was there before your program claimed it...
Whatever the program that previously ran in your address space put there. So if a program put, say, 77, at address 0xabcd5657, and then you read that address, you'd get 77. This is because C does not zero initialize memory for you, although you can yourself with memset:
memset(nchar, 0, 10);

Resources