Syntax related query during variable declaration and initialization - c

Consider the following code snippet
int main(){
int a, b, c;
printf("%d %d %d", a, b, c);
return 0;
}
This is going to display some garbage value.
Now, consider this snippet.
int main(){
int a, b, c = 0;
printf("%d %d %d", a, b, c);
return 0;
}
This displays 0 0 0 for every execution. But I've only initialized variable c to 0. Is this some shorthand for doing something like, int a=0, b=0, c=0;
Don't know how to look for such doubt in official documentation.

Without initialization, a, b are indeterminate right after int a, b, c = 0;
Their values are neither certainly consistent (they could be random) nor safe to access.
If an initialization is specified for the object, ...; otherwise, the value
becomes indeterminate each time the declaration is reached. C17dr §6.2.4 6
indeterminate value
either an unspecified value or a trap representation 3.19.2
unspecified value
valid value of the relevant type where this International Standard imposes no requirements on which value is chosen in any instance 3.19.3
trap representation
an object representation that need not represent a value of the object type 3.19.4
Didn't know how to look for such doubt in official documentation.
See Where do I find the current C or C++ standard documents? and search the spec for initialization.

Well, a and b are getting garbage on both examples. The only difference is that their garbage are different on each execution.
Like, they are put on an address that can contain anything, as, -2130381 or 83943097 or even 0. X% of the times you can get a 0 on an uninitialized value, and it will work on the first Y modifications of the code. After that, your code can just broke and you may spend some time debugging it.

Related

default values for long datatype in c programming

I am trying to add two long variables with default values. But one of the variable is getting assigned to value 1. But As per my knowledge it should get assigned with 0. why it was happening?
#include <stdio.h>
long add(long, long);
main()
{
long xno;
long zno;
long sum;
printf("xno = %d, zno = %d \n", xno, zno);
sum = add(xno, zno);
printf("sum = %d", sum);
}
long add(long x, long y) {
printf("x = %d, y = %d \n", x, y);
return x + y;
}
result:
xno = 0, zno = 1
x = 0, y = 1
sum = 1
result
Objects with automatic storage duration are not initialized by default. The C standard specifies they have “indeterminate” value, which means they do not have any fixed value. Essentially, it means your program is broken.
In a program where the objects had been initialized or had been assigned values, the compiler would manage their values properly: If it needed the value of xno and did not have it in a processor register already, the compiler would generate a load instruction to bring it into a register. If it had it in a register, it would use that register for the value of xno. So, in a working program, the compiler generates appropriate instructions.
What you are seeing is that, since xno and zno were never initialized or assigned values, the compiler is omitting the instructions that would load their values. Instead of filling a register with the value loaded from memory, the program executes using whatever data was in the register from some prior use. Further, the register the compiler uses for that may be different each time xno or zno is used. So a program could behave as if it is using different values for xno and zno each time they are used.
Further, in some circumstances, the C standard specifies that using an uninitialized automatic object has undefined behavior. (This occurs when the address of the object is never taken.) In this case, the C standard not only does not specify what value the object has, it does not specify what the behavior of the program is at all.
There is no default value for non static local variables in the c language.
You can think of having a non fixed 'random garbage value' for those declared variables.
Also, in printf for printing long you should use %ld rather than %d

Reading two integers, but inputting only one results in an indeterminate value being printed

I've just started learning C and would need some help here:
#include <stdio.h>
int main (){
int x, y;
scanf("%d/%d", &x, &y);
printf("%d,%d", x, y);
return 0
}
If I run the above code and only input 1 integer ('12'), it will print ('12,16'). Can someone explain how did the '16' come about?
If input stream contains just one number then the second value is not read. You would know that if you checked the return value:
int numbersread = scanf("%d/%d", &x, &y);
Then the y variable is uninitialized and it contains some garbage value. In your case it's 16.
The scanf function will fail to find a / character in the input and will stop reading there. It will not assign any value to y, which will remain uninitialized and will thus contain an indeterminate value. In your case, this was 16, but it could have been any other value, and this value could change when executing the program multiple times. The value is typically something that was used by the same process and was left in that memory location, and is now being interpreted as an int.
If the address of y was not taken, printing its value would have been undefined behavior (C11 6.3.2.1-2):
If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
However, since the address of y was taken (&y), its value is simply indeterminate. The lvalue y "is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion".
It is a good practice to always check the return value of scanf - which contains the "number of receiving arguments successfully assigned" - which allows you to handle the case of incorrect input.
Acknowledgements: Credits to Andreas Wenzel and Eric Postpischil for the correction on the origin of the indeterminate value.

Is 'printf("%n %d", &a, a)' well defined?

#include <stdio.h>
int main(void) {
int i = 0;
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
When I executed that, I got the following result.
abc 0
4
I thought that this result is intended.
But when I execute next one, I got a different result.
int main(void) {
int i; // not initialize
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
which produced:
abc 1
4
I don't know why the result of i in the first printf() is 1.
Even, I found more stranger behavior:
int main(void) {
int sdf;
printf("abc %n %d", &sdf, sdf);
printf("\n%d\n", sdf);
int i;
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
with this output:
abc 1
4
abc Random_Value
4
The first one always shows 1 but others show random value (I think this is garbage value).
I think garbage value was intended but I didn't get why the first one has a different result.
The value of an uninitialized local integer variable of storage class auto, that is stored in the stack area, is undefined. For this reason, printing it, a random value is absolutely expected.
That's why, in your output
abc 1
4
abc Random_Value
4
the value 1 is garbage as well.
In fact it is the first location in the stack, and its value could be different changing system and/or compiler. My guess is that its value is 1 because it represents a "ghost argc" that, being main a very special function, is present even if the function is defined without parameters, and its value is 1.
Since argc represents the number of parameters used to call your program from command line (at least 1: the executable name) there's a way to verify this hypotesis: call your program in this way
executableName foo
This would make argc become 2, so the value shown by that first printf should become 2 as well.
Out of curiosity, I tested this hypotesis by compiling your second example on my machine (DevC++ with gcc compiler under W10 64bit OS). I confirmed two statements:
When undefined behavior occurs, changing environment leads to a change in the output
argc is present in the stack and affects the initial value of the uninitialized local variables
Output after executing uninitVars.exe
abc
0
abc
1
Output after executing uninitVars.exe dog
abc
0
abc
2
Output after executing uninitVars.exe dog cat
abc
0
abc
3
So it seems that the first four bytes of my stack are always set to 0 (are they the location of the return value?) and that the second one is actually argc, even if it is not explicitly defined in the main() prototype.
The second print, instead, shows different values because it is defined after two printf calls, and their execution write several bytes in the stack (some of them are addresses, and that explains why the value is always different, as the addresses of a process are virtual and always different).
The result is well defined. Address of i and i are passed to the printf. Then printf assigns the value to i. But because i was passed before it, printf will print the value of i before the call.
The latter snippets use uninitialised variable and this undetermined value will be printed first. The behaviour later will be the same as per snipped 1.
The uninitialised variable will have undetermined value. It can be also an UB if the the type of the variable has trap representation (which is not the case here) But because the executing environment is the same, it is very likely that you will see the same values. If you run it on other OS, other computer or will use other compiler they will be probably different.
Is printf(“%n %d”, &a, a) defined well in printf?
If a has type int (equivalently, signed int) and is not const-qualified then yes, otherwise, no. In the well-defined case, the value of a at the time of the call is printed, and after the call returns, a will have the value 0.
Perhaps the key points here are that the arguments to a function call are evaluated before the called function is entered, and they are passed by value. There is a sequence point between the evaluation of the arguments and execution of the first statement in the function body, so the fact that a is read by the calling function and written by printf does not present any particular issue.
[...] when I execute next one, I got a different result.
int main(void)
{
int i; // not initialize
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
abc 1
4
I don't know why the result of 'i' in the first printf() is 1.
No one does. The value of an automatic variable that has neither been initialized nor assigned to is indeterminate. The same considerations apply here as in the title question: The expression i in printf's argument list is evaluated before the any part of printf executes, so the fact that printf will later assign a value to it does not affect the value it receives.
With the variable in question not being initialized, the behavior is at best unspecified and at worst undefined.
The local variables i and sdf are uninitialized, which means that their values are indeterminate. The formal definition is in section 3.19 of the C standard and is as follows:
3.19.2
1 indeterminate value
either an unspecified value or a trap representation
3.19.3
1 unspecified value
valid value of the relevant type where this International Standard imposes no requirements on
which value is chosen in any instance
2 NOTE An unspecified value cannot be a trap representation.
3.19.4
1 trap representation
an object representation that need not represent a value of the object type
This basically means that the value is unpredictable. In fact simply reading an indeterminate value can in some cases lead to undefined behavior. This can happen if the indeterminate value happens to be a trap representation as defined as above.
It can also be undefined behavior if the variable in question never had its address taken, however that doesn't apply in this case because you did take the address. This behavior is documented in section 6.3.2.1p2:
Except when it is the operand of the sizeof operator, the
_Alignof operator, the unary & operator, the ++ operator, the
-- operator, or the left operand of the . operator or an
assignment operator, an lvalue that does not have array type
is converted to the value stored in the designated object
(and is no longer an lvalue); this is called lvalue
conversion. If the lvalue has qualified type, the value has
the unqualified version of the type of the lvalue; additionally,
if the lvalue has atomic type, the value has the non-atomic version
of the type of the lvalue; otherwise, the value has the
type of the lvalue. If the lvalue has an incomplete type and does
not have array type, the behavior is undefined. If the lvalue
designates an object of automatic storage duration that could
have been declared with the register storage class (never had its
address taken), and that object is uninitialized (not declared
with an initializer and no assignment to it has been
performed prior to use), the behavior is undefined.
So assuming your implementation doesn't have trap representations, the values of sdf and i are unspecified, which means they could be any value, including 0 or 1. As an example, you get the values 1 and (some random value) for sdf and i. When I run the same code I get this:
abc 0
4
abc 0
4
And if I compile with -O3 which sets a higher optimization level, I get this:
abc 1446280512
4
abc 0
4
As you can see, running the came code as you that reads an unspecified value can have different results on different machines, or even on the same machine with different compiler settings.
There's nothing special about the value 0 that I got or the value 1 that you got. They're just as random as 1446280512.
First of all, you can not print the result of %n in the same line, i will keep its previous value. About the random value, while you have not initialized the i and sdf, they have a random value (most likely 0 but there is no guaranty). In C, global variables will have 0 value if they are not initialized, but the local variables will have uninitialized values (random).

Should variables always be initialized with literals?

main()
{
int a = 5, b = a, sum;
sum = a + b;
printf("sum is %d",sum);
}
In this C Program, will variable b be initialized at compile time or at run time?
Is it compile time initialization?
(C language)
No, variables should not always be initialised with literals, although some folk like to insure that variables are initialised at the point of declaration (and some firms insist on it) in order to avoid the reading of uninitialised variables in poorly crafted code.
As for any run-time behaviour: the as-if rule applies. Your source code merely describes what you want the behaviour to be, not the machine code that will be generated. Your variables will probably not exist in the compiled binary, which will be equivalent to
int main()
{
printf("sum is %d", 10);
}
(The expression int a = 5, b = a is well-defined since , is a sequencing point, so a is initialised at the time its value is read to assign to b.)
depends on whether the compiler/interpreter implemented the algorithm of constant propagation or not.
C standard does not impose not to use constant propagation. If one detects that that variable is not mutated it can be replaced with the precomputed value. The as-if rule says that one can do whatever optimization we want as time as the result is the expected one.

Why is the dereference of float pointer set to int variable's address printing as `0`?

I created the following code while playing with pointers -
#include <stdio.h>
int main()
{
float a=1000;
int *c=&a;
float *d=&a;
printf("\nValue of a is %f",a);
printf("\nValue of a is %f",*c);
printf("\nValue of a is %f",*d);
printf("\nValue of a is %f",*&*c);
printf("\nValue of a is %f\n",*&*d);
int b=2000;
int *e=&b;
float *f=&b;
printf("\nValue of b is %d",b);
printf("\nValue of b is %d",*e);
printf("\nValue of b is %d",*f); //Will produce 0 output
printf("\nValue of b is %d",*&*e);
printf("\nValue of b is %d\n",*&*f); //Will produce 0 output
float g=3000;
float *h=&g;
printf("\nValue of g is %f\n",*h);
}
Which has produced the output -
aalpanigrahi#aalpanigrahi-HP-Pavilion-g4-Notebook-PC:~/Desktop/C/Daily programs/pointers$ ./pointer004
Value of a is 1000.000000
Value of a is 1000.000000
Value of a is 1000.000000
Value of a is 1000.000000
Value of a is 1000.000000
Value of b is 2000
Value of b is 2000
Value of b is 0
Value of b is 2000
Value of b is 0
Value of g is 3000.000000
And For the second part where the variable b has been declared as integer and *e and *f are pointers , the value of b is printing out to be 0 in case of *f and *&*f (as shown in the code) but this has worked in the case above that where variable a has been declared as a floating point number.
Why is this happening ??
This issue is system depended.
In some platforms you will receive 0 and in some -1.
That is because you are printing the float as a int using the %d.
The float in most platform is 4 bytes (check it using sizeof(float)).
The binary value of the float number 2000 is 01000100111110100000000000000000 and it mark as a float so when you are trying to print it with %d it encounters undefined behavior.
Why is this happening ??
-shrugs- strange things happen when you try to fly planes backwards, with blindfolds and earplugs in. Thus, you should always learn to fly a plane by reading as much as possible before you jump into the cockpit.
Take off your blindfold and earplugs. Open your eyes, and get to reading a book. If you're already reading a book, get a new one, because this one's not working for you.
printf("\nValue of a is %f",*c); is undefined behaviour, because an attempt is made to print an expression which has type int (*c) using a format specifier which claims it's a double. C11/7.21.6.1p9 states this blatantly:
If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
Note that I didn't imply any consequences, positive or negative. It's undefined behaviour, meaning we can't tell whether it'll "work" (whatever that means) or whether it'll "crash".
Thus is the nature of UB. You probably didn't notice this error, because it "works", but it's not required to... moving on, we come to the example you ask about:
printf("\nValue of b is %d",*f);
A similar situation applies here; *f is a float expression, and %d tells scanf to expect an int value. The behaviour is undefined, which happens to mean in this case, you see a confusing "0".
You can not define the undefined by claiming it shouldn't print 0. It's allowed to print 0, because you've allowed it to by causing undefined behaviour. Similarly, if you were to see a crash, it's allowed to crash because you've allowed it to crash by causing undefined behaviour.
Also of relevance is C11/6.5p7:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:88)
a type compatible with the effective type of the object,
a qualified version of a type compatible with the effective type of the object,
a type that is the signed or unsigned type corresponding to the effective type of the object,
a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
a character type.
Hence, more often than not, if you're casting something you're likely making a mistake... a common mistake, involving not reading a book, for example... so... which book are you reading?

Resources