Is it good idea to pass uninitialized variable to srand? - c++

Is it good idea to pass uninitialized variable to srand instead of result of time(NULL)?
It is one #include and one function call less.
Example code:
#include <stdlib.h>
int main(void) {
{
usigned seed; //uninitialized
srand(seed);
}
//other code
return 0;
}
instead of
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL));
//other code
return 0;
}

No, it isn't.
Reading an uninitialized value results in undefined behavior. It can be zero, it can be semi-random — but as such, it can repeatedly be the same value. It may also cause compilation or runtime errors, or do any other completely unpredictable thing.
Then, someone else compiling your program will notice the compiler warning about uninitialized value and try to fix it. He may fix it correctly, or given complex enough program he may just initialize it to zero. That's how 'small' bugs turn into huge bugs.
Just try your snippet with srand() replaced by printf():
#include <stdio.h>
int main()
{
{
unsigned seed;
printf("%u\n", seed);
}
return 0;
}
On my system it repeatedly gives 0. This means that there's at least one system where your code is broken :).

No, accessing uninitialized variable is an undefined behavior. You should prefer time(NULL). Uninitialized variable method may introduce difficult to find bugs or may blow the computer.
Most of the time, effect observed would be, (on most implementation) above code would take (read) some leftover value from the stack that may be zero or something else but may be same on multiple runs defeating your purpose. time on the other hand is promising.

It's not a good idea. Undefined behaviour doesn't guarantee that you won't get the same seed on every run, which would be bad for randomness. It doesn't guarantee that your processor won't halt and catch fire either.

Another point is that uninitialized variables can result in a vulnerability. So it is not only bad design and undefined behaviour, it also can make your program exploitable.
Consider this code:
#include <stdio.h>
#include <time.h>
void print_uninitialized(void) {
unsigned var;
printf("%u\n", var);
}
void fake_init() {
unsigned var=42;
}
int main(void) {
print_uninitialized();
fake_init();
print_uninitialized();
}
Possible output:
0
42
The next example is a bit more realistic:
#include <stdio.h>
unsigned uninitialized( void ) {
unsigned var;
return var;
}
unsigned square(unsigned arg){
unsigned result=arg*arg;
return result;
}
int main( void ) {
unsigned to_square;
printf("UNINITIALIZED = %u\n", uninitialized());
while(scanf("%u", &to_square)!=EOF){
printf("%u * %u = %u\n", to_square, to_square, square(to_square));
printf("UNITNITIALIZED = %u\n", uninitialized());
}
}
The uninitialized variable can be modified by a user.
Input:
2
Output:
UNINITIALIZED = 0
2 * 2 = 4
UNITNITIALIZED = 4

In the first case there are two possibilities:
seed is a random variable (less possible)
seed is constant on every run (more possible)
time(NULL) returns the time of the system which is 99.99% different every time you run the code.
Nothing is perfect random, but using time(NULL) gives you a "more random" number then if you would use the first approach.
You should check function's usage
http://www.cplusplus.com/reference/cstdlib/srand/

Related

C++ initializes value for variable even though I left it empty, why does this happen?

For some reason, the value of final_sum is 16 but I didn't initialize a value for that variable, why's that? Isn't supposed to start with 0?
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main()
{
int n, sum, final_sum;
cout<<"ff: "<<final_sum<<endl;
cout<<"Input the value for n: ";
cin>>n;
for(int i=1; i<=n; i++){
sum += i;
final_sum += sum;
cout<<"sum: "<<sum<<endl;
cout<<"final sum: "<<final_sum<<endl<<endl;
}
return 0;
}
Isn't supposed to start with 0
No, its initial value is undefined. See https://en.cppreference.com/w/cpp/language/default_initialization
the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values.
If you do
int final_sum{};
Or
int final_sum = 0;
You will have a 0 in your variable.
I suggest you to use -Wuninitialized (or better -Wall). The compiler will raise a warning if you forgot and initialization
If you don't initialize a variable before reading/using it, its undefined behavior. Its value can then be anything, it's unpredictable and always a bad idea. Use
int final_sum = 0;
to initialize it.
From documentation:
The value in an uninitialized variable can be anything – it is
unpredictable, and may be different every time the program is run.
Reading the value of an uninitialized variable is undefined behaviour
– which is always a bad idea. It has to be initialized with a value
before you can use it.
and
The only place where they are useful is when you are about to read the
variable in from some input stream.
Edit : Some may ask "Why my variable still print 0 even though I haven't initialize it?"
From this post :
That is because variables with automatic storage duration are not
automatically initialized to zero in C++. In C++, you don't pay for
what you don't need, and automatically initializing a variable takes
time (setting to zero a memory location ultimately reduces to machine
intruction(s) which are then translated to electrical signals that
control the physical bits).
So when you do :
int final_sum;
The final_sum is just being reserved a memory location, and anything currently inside that location will be printed out by cout. It just happened that there's a big 0 in that spot.
More info : (Why) is using an uninitialized variable undefined behavior?
Declaring the variable globally does the job
int final_sum;
int main() {
your code ...
}
is the same as
int final_sum = 0;
int main() {
your code here ...
}
However, you probably don't want to use global variables and it is always recommended to initialize variables with some value.

why does this recursion program work?

#include <iostream>
using namespace std;
int main() {
int n,x;
int fact(int);
cin >> n;
x = fact(n);
cout << x;
return 0;
}
int fact(int n) {
if(n!=1)
return n*fact(n-1);
}
In the last case, when the argument passed to the function fact is 1, how is it able to calculate that fact(1) is equal to 1, without me specifying it in my code?
This program relies on undefined behavior. It is certainly not guaranteed to work, but you may have found a situation in which the parameter you send (1) is in a place where the calling code perceives it as the return value. Do not depend on this behavior.
Many C++ compilers would reject this code as having a semantic issue: Not all control paths return a value from fact()
int fact(int n);
This function signature returns an integer, but when n=1 is given there is no corresponding return statement in your implementation. In that case, the function may return any int value (i.e. garbage in memory) and the behaviour is undefined. You should not depend on this, even though your compiler allows it to run.
I'm quite certain you saw a warning when compiling your program. In my environment (g++ on Mac OSX), the compiler issued the following warning:
warning: control may reach end of non-void function [-Wreturn-type]
Personally, I don't think there is any good reason for a compiler to allow this kind of bug (i.e. it should fail to compile).
Reference: A similar question is found below:
C++ return value without return statement

How does this code section print 5?

#include <iostream>
using namespace std;
int main() {
cout<<(int *)16 - (int *)10 ;
return 0;
}
This code section produces an output 5, i could not understand the output?
There is no point in rationalising about this: you do not have an array that contains elements who live at 10 and 16 in memory. Therefore, the subtraction operation is undefined and anything can happen.
Speaking practically, since the difference between the two addresses is [probably] not a multiple of sizeof(int), your compiler appears to be chickening out and returning abject nonsense.
Fortunately, you never have a reason to write this code in your projects, so it doesn't matter.

Optimize non-cost variable access

There's an interesting optimization problem I'm facing.
In a large code base, consisting of a large number of classes, in many places the value of a non-constant global (=file scope) variable is very often used/examined and the unnecessary memory accesses of this variable are to be avoided.
This variable is initialized once, but because of the complexity of its initialization and the need to call a number of functions, it cannot be initialized like this, before execution of main():
unsigned size = 1000;
int main()
{
// some code
}
or
unsigned size = CalculateSize();
int main()
{
// some code
}
Instead it has to be initialized like this:
unsigned size;
int main()
{
// some code
size = CalculateSize();
// lots of code (statically/dynamically created class objects, whatnot)
// that makes use of "size"
return 0;
}
Just because size isn't a constant and it is global (=file scope) and the code is large and complex, the compiler is unable to infer that size never changes after size = CalculateSize();. The compiler generates code that fetches and refetches the value of size from the variable and can't "cache" it in a register or in a local (on-stack) variable that's likely to be in the CPU's d-cache together with other frequently accessed local variables.
So, if I have something like the following (a made-up example for illustrative purposes):
size = CalculateSize();
if (size > 200) blah1();
blah2();
if (size > 200) blah3();
The compiler thinks that blah1() and blah2() may change size and it generates a memory read from size in if (size > 200) blah3();.
I'd like to avoid that extra read whenever and wherever possible.
Obviously, hacks like this:
const unsigned size = 0;
int main()
{
// some code
*(unsigned*)&size = CalculateSize();
// lots more code
}
won't do as they invoke undefined behavior.
The question is how to inform the compiler that it can "cache" the value of size once size = CalculateSize(); has been performed and do it without invoking undefined behavior, unspecified behavior and, hopefully, implementation-specific behavior.
This is needed for C++03 and g++ (4.x.x). C++11 may or may not be an option, I'm not sure, I'm trying to avoid using advanced/modern C++ features to stay within the coding guidelines and predefined toolset.
So far I've only come up with a hack to create a constant copy of size within every class that's using it and use the copy, something like this (decltype makes it C++11, but we can do without decltype):
#include <iostream>
using namespace std;
volatile unsigned initValue = 255;
unsigned size;
#define CACHE_VAL(name) \
const struct CachedVal ## name \
{ \
CachedVal ## name() { this->val = ::name; } \
decltype(::name) val; \
} _CachedVal ## name;
#define CACHED(name) \
_CachedVal ## name . val
class C
{
public:
C() { cout << CACHED(size) << endl; }
CACHE_VAL(size);
};
int main()
{
size = initValue;
C c;
return 0;
}
The above may only help up to a point. Are there better and more suggestive-to-the-compiler alternatives that are legal C++? Hoping for a minimally intrusive (source-code-wise) solution.
UPDATE: To make it a bit more clear, this is in a performance-sensitive application. It's not that I'm trying to get rid of unnecessary reads of that particular variable out of whim. I'm trying to let/make the compiler produce more optimal code. Any solution that involves reading/writing another variable as often as size and any additional code in the solution (especially with branching and conditional branching) executed as often as size is referred to is also going to affect the performance. I don't want to win in one place only to lose the same or even more in another place.
Here's a related non-solution, causing UB (at least in C).
There's the register keyword in C++ which tells the compiler you plan on using a variable a lot. Don't know about the compiler you're using, but most of the modern compilers do that for the users, adding a variable into the registry if needed. You can also declare the variable as constant and initialize it using const_cast.
what of:
const unsigned getSize( void )
{
static const unsigned size = calculateSize();
return size;
}
This will delay the initialization of size until the first call to getSize(), but still keep it const.
GCC 4.8.2
#include <iostream>
unsigned calculate() {
std::cout<<"calculate()\n";
return 42;
}
const unsigned mySize() {
std::cout<<"mySize()\n";
static const unsigned someSize = calculate();
return someSize;
}
int main() {
std::cout<<"main()\n";
mySize();
}
prints:
main()
mySize()
calculate()
on GCC 4.8.0
Checking for whether it has been initialized already or not will be almost fully mitigated by the branch predictor. You will end up having one false and a quadrillion trues afterwards.
Yes, you will still have to access that state after the pipeline has been basically built, potentially wreaking havoc in the caches, but you can't be sure unless you profile.
Also, compiler can likely do some extra magic for you (and it is what you're looking for), so I suggest you first compile and profile with this approach before discarding it entirely.

Unexpected output

#include <iostream>
int main()
{
const int i=10;
int *p =(int *) &i;
*p = 5;
cout<<&i<<" "<<p<<"\n";
cout<<i<<" "<<*p;
return 0;
}
Output:
0x22ff44 0x22ff44
10 5
Please Explain.
Well, your code obviously contains undefined behaviour, so anything can happen.
In this case, I believe what happens is this:
In C++, const ints are considered to be compile-time constants. In your example, the compiler basically replaces your "i" with number 10.
You've attempted to modify a const object, so the behavior is
undefined. The compiler has the right to suppose that the const
object's value doesn't change, which probably explains the
symptoms you see. The compiler also has the right to put the
const object in read only memory. It generally won't do so for
a variable with auto lifetime, but a lot will if the const has
static lifetime; in that case, the program will crash (on most
systems).
I'll take a shot at it: since there's no logical reason for that output, the compiler must have optimised that wretched cout<<i<<" " to a simple "cout<<"10 ". But it's just a hunch.