I'm using MSVC and it seems like the code below does not crash and the function pointer is initialized to NULL by the compiler.
int (*operate)(int a, int b);
int add(int a, int b)
{
return a + b;
}
int subtract(int a, int b)
{
return a - b;
}
int main()
{
if(operate) //would crash here if not NULL
{
cout << operate(5,5);
}
operate = add;
if(operate)
{
cout << operate(5,5);
}
operate = subtract;
if(operate)
{
cout << operate(5,5);
}
return 0;
}
So it seems MSVC initializes function pointers to NULL, but if I build this on gcc in Linux would it also be NULL? Is it conventional or MSVC specific, can I rely on it being NULL wherever I go?
Thanks
operate is initialised to NULL because it is a global variable, not because it is a function pointer. All objects with static storage duration (which includes global variables, file-level static variables and static variables in functions) are initialised to 0 or NULL if no initialiser is given.
[EDIT in response to Jim Buck's comment:]
In C++, this is guaranteed by clause 3.6.2/1 of the language standard, which begins:
Objects with static storage duration
(3.7.1) shall be zero-initialized
(8.5) before any other initialization
takes place. Zero-initialization and
initialization with a constant
expression are collectively called
static initialization; all other
initialization is dynamic
initialization.
I expect the same behaviour is true of C, since C++ is designed to be compatible with it on most things, although I don't have the standard for it.
[EDIT #2] As Jeff M points out in a comment, it's important to realise that variables of automatic storage duration (that is, "ordinary" local variables) are not automatically zero-initialised: unless an initialiser is given, or they are assigned values by a constructor, they will initially contain random garbage (whatever was already sitting in memory at that location). So it's a good habit to initialise all variables -- it can't hurt but can help.
Related
How do we know pointers are not initialized to NULL by default?
There is a similar questions directed at Why aren't pointers initialized with NULL by default?
Just for checking, here is a very simple code just to see if a pointer is set to NULL by default.
#include <iostream>
using namespace std;
int main()
{
int* x;
if(!x)
cout << "nullptr" << endl;
return 0;
}
and at the output, I received nullptr message. I appreciate if someone can clarify this.
How do we know pointers are not initialized to NULL by default?
Because we know that the standard says that default initialised pointer has an indeterminate value if it has automatic or dynamic storage. Quote from the standard (draft):
[dcl.init] If no initializer is specified for an object, the object is default-initialized. When storage for an object
with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if
no initialization is performed for the object, that object retains an indeterminate value until that value
is replaced. ...
And further:
[dcl.init] To default-initialize an object of type T means:
— If T is a (possibly cv-qualified) class type [pointer isn't a class, so we don't care]
— If T is an array type [pointer isn't an array, so we don't care]
— Otherwise, no initialization is performed.
I have declared a char (and also int) pointer without initializing it , and I got null pointers.
Reading an indeterminate value has undefined behaviour. Quote from the standard (draft):
[dcl.init] ... If an indeterminate value is produced by an evaluation, the behavior is undefined except in the
following cases: [cases which don't apply here]
The question you linked to handles variables with local storage duration exclusively, so I assume you refer to these as well.
Such variables are not initialised if you don't do so yourself, so they get the value of whatever was written in their memory location before (standard wording: their value is 'indeterminate') – nothing speaks against, though, that this memory already is zero – by pure accident!
You can try the following:
void test()
{
int* p; // uninitialized
std::cout << p << std::endl; // undefined behaviour!!!
// (that's what you most likely did already...)
// now something new: change the memory...
p = reinterpret_cast<int*>(static_cast<uintptr_t(0xaddadaad));
}
int main()
{
test();
// again something new: call it a SECOND time:
test();
}
As this is undefined behaviour there are no guarantees at all that you will get any meaningful output – chances are, though that the memory of first function call is reused in second one and you might get output ressembling to the following:
00000000
addadaad
So even if there just happened to be all zero memory at programme start, it might differ from that at some later point while your programme is running...
I was recently reviewing some code and I came across something that I was confused about. Say I have a functions, int getNewNumber(int num, int dir), implemented like this:
int getNewNumber(int num, int dir) {
int newNum = num;
if(dir == 1) {
newNum++;
} else {
newNum--;
}
return newNum;
}
Now, when calling the function, I have something like this:
int number = getNewNumber(number, 1);
Is it initialized to 0 before being passed into newNum? I'm confused about how you can use the variable as an argument when it's being initialized.
Is it initialized to 0 before being passed into newNum?
Maybe. It depends on context. If the variable is a global static, then it is zero initialized before dynamic initialization.
If it is an automatic variable, then the value passed into getNewNumber is indeterminate and using that value has undefined behaviour. A decent compiler will warn you.
I'm confused about how you can use the variable as an argument when it's being initialized.
If the variable wasn't initialized statically, then you can't use its value in its own initialization in a way that would have defined behaviour.
If the variable was zero initialized before dynamic initialization, then you can use the value, but you might as well use literal zero, and that would be clearer to the reader of the program. I don't think there is any useful way to use the value of a variable in its own initialization.
I really think it depends on the compiler. In general I'd call it unsafe - in the best case you'll get a a value, that has the same type, or can be converted to this type. In the worst case - the program will simply crash.
I accidentally created a bug in a program by self-referencing in an array. Here's a very simplified demo program similar in concept:
#include <iostream>
using namespace std;
int kTest[] = {
kTest[0]
};
int main() {
cout << kTest[0] << endl;
}
I was surprised that I received neither a compiler error or even a warning on this code! In my case it ended up producing unpredictable output. Is it accessing garbage memory?
I was curious about under what circumstances this would have well-defined output (if ever!).
Edit: Does it make a difference if kTest is static? What about const? Both?
int kTest[] = {
kTest[0]
};
is similar to, if not exactly same as
int x = x;
It will be undefined behavior, if declared locally in a function.
It seems to be well defined when kTest is a global variable. See the other answer for additional details.
I'm not so sure this is undefined. Quote from the current draft:
[basic.start.static]/3
If constant initialization is not performed, a variable with static
storage duration ([basic.stc.static]) or thread storage duration
([basic.stc.thread]) is zero-initialized ([dcl.init]). Together,
zero-initialization and constant initialization are called static
initialization; all other initialization is dynamic initialization.
Static initialization shall be performed before any dynamic initialization takes place.
To me it looks like kTest is already zero-initialized when the dynamic initialization starts, so it may be defined to initialize to 0.
I have encountered a problem in my learning of C++, where a local variable in a function is being passed to the local variable with the same name in another function, both of these functions run in main().
When this is run,
#include <iostream>
using namespace std;
void next();
void again();
int main()
{
int a = 2;
cout << a << endl;
next();
again();
return 0;
}
void next()
{
int a = 5;
cout << a << endl;
}
void again()
{
int a;
cout << a << endl;
}
it outputs:
2
5
5
I expected that again() would say null or 0 since 'a' is declared again there, and yet it seems to use the value that 'a' was assigned in next().
Why does next() pass the value of local variable 'a' to again() if 'a' is declared another time in again()?
http://en.cppreference.com/w/cpp/language/ub
You're correct, an uninitialized variable is a no-no. However, you are allowed to declare a variable and not initialize it until later. Memory is set aside to hold the integer, but what value happens to be in that memory until you do so can be anything at all. Some compilers will auto-initialize variables to junk values (to help you catch bugs), some will auto-initialize to default values, and some do nothing at all. C++ itself promises nothing, hence it's undefined behavior. In your case, with your simple program, it's easy enough to imagine how the compiler created assembly code that reused that exact same piece of memory without altering it. However, that's blind luck, and even in your simple program isn't guaranteed to happen. These types of bugs can actually be fairly insidious, so make it a rule: Be vigilant about uninitialized variables.
An uninitialized non-static local variable of *built-in type (phew! that was a mouthful) has an indeterminate value. Except for the char types, using that value yields formally Undefined Behavior, a.k.a. UB. Anything can happen, including the behavior that you see.
Apparently with your compiler and options, the stack area that was used for a in the call of next, was not used for something else until the call of again, where it was reused for the a in again, now with the same value as before.
But you cannot rely on that. With UB anything, or nothing, can happen.
* Or more generally of POD type, Plain Old Data. The standard's specification of this is somewhat complicated. In C++11 it starts with §8.5/11, “If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value.”. Where “automatic … storage duration” includes the case of local non-static variable. And where the “no initialization” can occur in two ways via §8.5/6 that defines default initialization, namely either via a do-nothing default constructor, or via the object not being of class or array type.
This is completely coincidental and undefined behavior.
What's happened is that you have two functions called immediately after one another. Both will have more or less identical function prologs and both reserve a variable of exactly the same size on the stack.
Since there are no other variables in play and the stack is not modified between the calls, you just happen to end up with the local variable in the second function "landing" in the same place as the previous function's local variable.
Clearly, this is not good to rely upon. In fact, it's a perfect example of why you should always initialize variables!
Let us have the variable
char *s;
I know if it's declared in global scope, its value should be 0;
If it's declared in local scope, its value is undefined (it may be 0 though).
I've got a question in test which sounds like this 'What will be the value of the pointer defined as
char* s
a) null
b) empty string
c) undefined
I'm really confused what answer I should choose, because if it's declared in global scope, well, the value would be null (i guess). If it's declared in local scope, undefined (though when I tried it's zero), and when I try to cout it, nothing is printed (no segmentation fault, why?), that means it's an empty string (or is cout that awesome?).
The question you quoted is most likely written by a person who didn't fully understand the issue. As you correctly noted, the initial value of such pointer greatly depends on the context: where and how it is defined (local, static, aggregate member?). So, the correct answer should be an expanded one that explains these dependencies. It is weird to attempt to answer such question in a "multiple choice, only one of many" fashion.
Of course, in very general and most formally pedantic sense, the correct answer is the one that says "undefined", since in general case, not knowing where it is defined, we have to "assume the worst". But I doubt the author of the test realized that.
In this case the value is definitely undefined by standard. Compilers will however often default initialize it to zero in debug mode.
When you print it out, cout doesn't do any magig, it will find a 0 and it will not print out anything.
Here are the rules for default initialization:
when a variable with automatic, static, or thread-local storage duration is declared with no initializer
when an object with dynamic storage duration is created by a new-expression without an initializer
when a base class or a non-static data member is not mentioned in a constructor initializer list and that constructor is called.
For example:
#include <string>
struct T1 {};
class T2 {
int mem;
public:
T2() {} // "mem" not in initializer list
};
int n; // This is not default-initialization, the value is zero.
int main()
{
int n; // non-class: the value is undeterminate
std::string s; // calls default ctor, the value is "" (empty string)
std::string a[2]; // calls default ctor, creates two empty strings
// int& r; // error: default-initializing a reference
// const int n; // error: const non-class type
// const T1 nd; // error: const class type with implicit ctor
T1 t1; // ok, calls implicit default ctor
const T2 t2; // ok, calls the user-provided default ctor
// t2.mem is default-initialized (to indeterminate value)
}
Source