Default value for pointer to char in C - c++

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

Related

How to Initialize all Variables in the program to zero without doing it explicitly in c++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I want to make all the variables which I create in my program to have initialization to zero without doing it explicitly.
For example suppose if I create a variable like below:
int i;
We know that it must contain any garbage value and to make it have value 0 by default we need to declare it like
int i=0;
but I want my all variables in the program to contain garbage value as 0 not any other value.
In my code I want my every variables (which include class variables, global variables, local variables) to automatically initialize to 0 without doing it explicitly.
So what logic I tried is that in C, I have written the "Hello World" program without using main() function. So what I have done in that time is to override the _start function which is the first function called by compiler to set up everything and then call to main(). So I think there must be a function which compiler calls during the creation of a variables and I thought we can set the value 0 to the all variables there. Please help me with this problem. If there exist some other logic to solve this problem you can share with me I am open to all solutions but please don't say to explicitly declare them with the value 0.
As a person who spends much of his working life looking at other people's broken code, I really have to say this, although I doubt it will be popular...
If it matters what the initial value of a variable is, then you should initialize it explicitly.
That's true even if you initialize it to what is, in fact, the default value. When I look at a statement like this:
int i = 0;
I immediately know (or think I know) that the programmer really thought about the value, and set it. If I read this:
int i;
then I assume that the programmer does not care about the value -- presumably because it will be assigned a value later.
So far as automatic variables are concerned, it would be easy enough for the compiler to generate code that zero'd the relevant part of the stack frame on entry to a function. I suspect it would be hard to do in application code; but why would you want to? Not only would it make the program behave in a way that appears to violate the language specifications, it would encourage slopping, unreadable programming practices.
Just initialize your variables, and have done with it. Or, if you don't want to initialize it because you know that the compiler will initialize it in the way you want, insert a comment to that effect. You'll thank yourself when you have to fix a bug five years later.
Default initialization and some words regarding the complexity of initialization in C++
To limit the scope of this discussion, let T be any kind of type (fundamental such as int, class types, aggregate as well as non-aggregate), and the t be a variable of automatic storage duration:
int main() {
T t; // default initialization
}
The declaration of t means t will be initialized by means of default initialization. Default initialization acts differently for different kind of types:
For fundamental types such as int, bool, float and so on, the effect is that t is left in an uninitialized state, and reading from it before explicitly initializing it (later) is undefined behavior
For class types, overload resolution resolve to a default constructor (which may be implicitly or implicitly generated), which will initialize the object but where its data member object could end up in an uninitialized state, depending on the definition of the default constructor selected
For array types, every element of the array is default-initialize, following the rules above
C++ initialization is complex, and there are many special rules and gotchas that can end up with uninitialized variable or data members of variables whence read results in UB.
Hence a long-standing recommendation is to always explicitly initialized you variables (with automatic storage duration), and not rely on the fact that default initialization may or may not result in a fully initialized variable. A common approach is (attempting) to use value initialization, by means of initialization of variable with empty braces:
int main() {
int i{}; // value-initialization -> zero-initialization
SomeAggregateClass ac{}; // aggregate initialization
}
However even this approach can fail for class types if one is not careful whether the class is an aggregate or not:
struct A {
A() = default; // not user-provided.
int a;
};
struct B {
B(); // user-provided.
int b;
};
// Out of line definition: a user-provided
// explicitly-defaulted constructor.
B::B() = default;
In this example (in C++11 through C++17), A is an aggregate, whereas B is not. This, in turn, means that initialization of B by means of an empty direct-list-init will result in its data member b being left in an uninitialized state. For A, however, the same initialization syntax will result in (via aggregate initialization of the A object and subsequent value initalization of its data member a) zero-initialization of its data member a:
A a{};
// Empty brace direct-list-init:
// -> A has no user-provided constructor
// -> aggregate initialization
// -> data member 'a' is value-initialized
// -> data member 'a' is zero-initialized
B b{};
// Empty brace direct-list-init:
// -> B has a user-provided constructor
// -> value-initialization
// -> default-initialization
// -> the explicitly-defaulted constructor will
// not initialize the data member 'b'
// -> data member 'b' is left in an unititialized state
This may come as a surprise, and with the obvious risk of reading the uninitialized data member b with the result of undefined behaviour:
A a{};
B b{}; // may appear as a sound and complete initialization of 'b'.
a.a = b.b; // reading uninitialized 'b.b': undefined behaviour.

const correctness with const objects and member pointers, constructor vulnerability

class Test
{
public:
Test() : i(0), ptr(&i) {}
int i;
int *ptr;
void change_const (int x) const { *ptr=x; }
};
int main()
{
const Test obj;
obj.ptr = &obj.i; // error
obj.change_const(99);
return 0;
}
Although in obj ptr is of type int *const, the constructor can make him point to i of type const int. An explicit try to do this of course fails. Why does a constructor offer this vulnerability regarding const correctness? Other non directly obvious vulnerabilities like
int *ptr;
const int **c_ptr = &ptr; // error
const int c = 10;
*c_ptr = &c;
*ptr = 20; // because here change of c possible
are also well thought prevented.
const is a language-level concept. That is, when you compile your code and execute it as machine code, all data is seen as data more or less. Note that I say "more or less" because we are ignoring the fact that, in theory, const data could be stored in read-only pages and trigger page faults when written to; but this is not common due to the granularity of page sizes. So what is happening is the following:
Your constructor initializes that value of ptr to point to the address of i. Since your obj object is const, you could not directly modify the value of i and, further, you could not change where ptr points to. However, you can access and manipulate the memory that ptr points to (in this case, the value of i).
Therefore, since the compiler doesn't check/know/care that ptr is pointing to i, it does not catch the violation of const. Instead, it just sees you modifying the data pointed to by ptr.
Clearly the constructor (or at least the initializer list if not the body of the ctor) needs to be able to write a value to i.
As it happens, the way C++ achieves this is to make this a pointer-to-non-const in the constructor (and destructor). Basically, the const-ness of obj doesn't commence until the constructor has finished executing. That's why the vulnerability exists, because of a straightforward but imperfect solution to the technical problem of how to construct const-qualified objects.
Perhaps it could in principle be done differently. I suppose you'd need a separate const version of the constructor in which the compiler applies different rules (just as normal member functions can be const), treating data members as const and therefore (1) allowing them to be initialized but not assigned, (2) forbidding the initialization of ptr from &i since the latter would have type int const*. C++ doesn't do this, and as a result it has this loophole that you've driven through. If it did do it, people would have more difficulty writing constructors in certain cases, so it's a design trade-off.
Be aware that similarly a volatile-qualified object is not volatile in its own constructor or destructor.
Steve Jessop answered it, but for what it's worth, here is the quote from the Standard (emphasis mine):
12.1/4 A constructor shall not be virtual (10.3) or static (9.4). A constructor can be invoked for a const, volatile or const volatile object. A constructor shall not be declared const, volatile, or const volatile (9.3.2). const and volatile semantics (7.1.6.1) are not applied on an object under construction. They come into effect when the constructor for the most derived object (1.8) ends. A constructor shall not be declared with a ref-qualifier.
So *this is not a constant object from the point of view of the constructor, even when a constant object is created. This could have been designed differently, but then constructors of constant objects would be much less flexible than constructors of non-constant objects; for example, they would always have to initialize all members in the initializer list; they could not use loops etc. in the body of the constructor to set values for complex members.

At what point does the memory get allocated to a constant variable in c++?

As much as i know, constant class members must be initialized before the constructor runs, but since they cannot be initialized in the class body (as it is just a prototype), therefore we need to initialize it inside initializer list. My question is when does memory gets allocated to a constant variable, and what is the order of execution?
class constant
{
const int a;
public:
constant(int k):a(k)
{
cout<<"a is "<<a<<endl;
}
};
int main()
{
constant cl(5);
return 0;
}
EDIT: Is it true that constant variables need to be initialized at the point where they are allocated memory?
I think you have the wrong idea about const. Think less of it as related to implementation details (like memory), or runtime, and more there as a means to help the programmer and for the compiler.
It doesn't matter when the memory gets allocated (although it's before you construct the object, before entering the initializer list - not specified by the standard), what matters is you can only initialize the variable in the intializer list (pre C++11) or even the class definition for const integral types.
when does memory gets allocated to a constant variable
Here, a is a data member of class constant, so it's allocated as part of constant. Whenever you create an instance of constant, there's an a already included.
Note that static members are different, but just because a isn't allowed to change after initialization, doesn't make its storage different from any other regular data member.
... is it necessary that constant variables be initialized at the point where they are allocated memory
Strictly, you have to have the memory available before you can call the constructor, so the phrase at the point where is a bit problematic (see specifically André Caron's comment about placement new).
However, allocation and construction are tied together in most normal use, and initialization of a const member must happen when the object is constructed.
If the variable is const, the compiler enforces you to not change that value after initialization. That is, you must initialize it (must in the sense of RFC2119).
You must directly initialize it:
struct constant {
const int a;
constant(int k) : a(k) {
/* everything is fine here */
}
};
You must not leave it uninitialized:
struct constant {
const int a;
constant(int k) {
/* error: uninitialized member ‘constant::a’ with ‘const’ type ‘const int’ */
}
};
And you must not change it's value after construction:
struct constant {
const int a;
constant(int k) {
a = k;
/* error: uninitialized member ‘constant::a’ with ‘const’ type ‘const int’ */
/* error: assignment of read-only data-member ‘constant::a’ */
}
};
Exact memory place for object members depends from object creation.
If you create object by "new" it is would be a heap.
If you create stack object (like on your example) it is would be a stack memory.
"Constant" memory - it is memory for "constant", not for "const variables".
Other words, const memory used for literal strings, literal numbers ("text", 5), while a const modifier restrict the memory update.

Construction of const object

C++11 §12.1/14:
During the construction of a const object, if the value of the object or any of its subobjects is accessed through an lvalue that is
not obtained, directly or indirectly, from the constructor’s this
pointer, the value of the object or subobject thus obtained is
unspecified. [Example:
struct C;
void no_opt(C*);
struct C {
int c;
C() : c(0) { no_opt(this); }
};
const C cobj;
void no_opt(C* cptr) {
// value of cobj.c is unspecified
int i = cobj.c * 100;
cptr->c = 1;
// value of cobj.c is unspecified
cout << cobj.c * 100 << '\n';
}
Compiling the above example outputs 100. My question is why is the value of cobj.c should be unspecified when the initialization list sets it to 0 before entering constructor? How is this behavior different in case if a non-const object is used?
Genuinely const objects may be treated by the compiler as legitimate constants. It can assume their values never change or even store them in const memory, e.g. ROM or Flash. So, you need to use the non-const access path provided by this as long as the object is, in fact, not constant. This condition only exists during object construction and destruction.
Offhand, I think there does not need to be a corresponding requirement for destructors because the object lifetime has already ended and cobj.c is inaccessible as soon as the destructor for cobj begins.
As Matthieu mentions, it is a strong "code smell" to be accessing an object besides through this during construction or destruction. Reviewing C++11 §3.8 [basic.life] ¶1 and 6, it would appear that cobj.c inside the constructor is UB for the same reason it is inside the destructor, regardless of the object being const or §12.1/14, because its lifetime does not begin until initialization is complete (the constructor returns).
It might be likely to work, but it will ring alarms for good C++ programmers, and by the book it is illegal.
The reason for the quoted rule is to allow the compiler to make
optimizations based on the const-ness of the object. For example,
depending on optimization, your compiler might replace the second
cobj.c * 100 in no_opt with i. More likely, in this particular
case, the optimizer will suppress the i and its initialization
completely, so the code will appear to work. But this might not be the
case if you also output i, before changing cptr->c; it all depends
on how agressive the compiler optimizes. But the compiler is allowed to
assume that *cptr is not an alias for cobj, because cobj is a
const object, where as you modify through *cptr, so it cannot point to
a const object without undefined behavior.
If the object isn't const, of course, the issue doesn't occur; the
compiler must always take into account a possible aliasing between
*cptr and cobj.

C++ - value of uninitialized vector<int>

I understand from the answer to this question that values of global/static uninitialized int will be 0. The answer to this one says that for vectors, the default constructor for the object type will be called.
I am unable to figure out - what happens when I have vector<int> v(10) in a local function. What is the default constructor for int? What if I have vector<int> v(10) declared globally?
What I am seeing is that vector<int> v(10) in a local function is resulting in variables being 0 - but I am not sure if that is just because of my compiler or is the fixed expected behaviour.
The zero initialization is specified in the standard as default zero initialization/value initialization for builtin types, primarily to support just this type of case in template use.
Note that this behavior is different from a local variable such as int x; which leaves the value uninitialized (as in the C language that behavior is inherited from).
It is not undefined behaviour, a vector automatically initialises all its elements. You can select a different default if you want.
The constructor is:
vector( size_type, T t = T() )
and for int, the default type (returned by int()) is 0.
In a local function this:
int x;
is not guaranteed to initialise the variable to 0.
int x = int();
would do so.
int x();
sadly does neither but declares a function.
The constructor you are using actually takes two arguments, the second of which is optional. Its declaration looks like this:
explicit vector(size_type n, const T& value = T())
The first argument is the number of elements to create in the vector initially; the second argument is the value to copy into each of those elements.
For any object type T, T() is called "value initialization." For numeric types, it gives you 0. For a class type with a default constructor, it gives you an object that has been default constructed using that constructor.
For more details on the "magic parentheses," I'd recommend reading Michael Burr's excellent answer to the question "Do the parentheses after the type name make a difference with new?" It discusses value initialization when used with new specifically, but for the most part is applicable to value initialization wherever else it can be used.
By default, vector elements are zero-initialized and not default-initialized. Those are two different but related concepts:
zero-initialization is what is done for static objects not having an explicit initialization and what is done for a member given in the initialized list with an initializer of (). For basic types, the value used is 0 converted to the type.
default-initialization is what is done for not explicitly initialized non static variables and members. For basic types it stay uninitialized.
(And C++0X introduces value-initialization which is still different).
As mentioned by others, what happens is the zero initialization kicks in. I actually use that a lot in my code (outside of vectors and other classes):
some_type my_var = some_type();
This allows me to make sure that my variables are always properly initialized since by default C/C++ do not initialize basic types (char, short, int, long, float, double, etc.)
Since C++11, you also can do so in your class definitions:
class MyClass
{
...
int my_field_ = 123; // explicit initialization
int your_field_ = int(); // zero initialization
};
For vectors, the std library uses T(). Whatever T() is, it will use that default initialization. For a class, it calls the default constructor. For a basic type, it uses zero ('\0', 0, 0.0f, 0.0, nullptr`).
As mentioned by James McNellis and Nawaz, it is possible to set the value used to initialize the vector as in:
std::vector<int> foo(100, 1234);
That feature is also available when you resize your vector (if the vector shrinks, the default value is ignored):
foo.resize(200, 1234);
So that way you can have a default initialization value. However, it's a be tricky since you have to make sure that all your definitions and resize() calls use that default value. That's when you want to write your own class which ensures that the default value is always passed to the vector functions.
However, if you want to have a way to auto-initialize to a specific value, you can mix both features this way:
struct my_value {
int v = 123;
};
std::vector<my_value> foo(100);
// here foo[n].v == 123 for n in [0, 100)
This is my preferred way of dealing with this issue (i.e. if I don't want zero by default). It's an extra .v, but much less prone to mistakes and you don't need to know of the default value when you create a vector of my_value.
Also, for those who think this will be slow, it won't. The struct is like syntactic sugar as far as C++ is concerned. One optimized, it will be exactly the same as a simple std::vector<int> foo(100, 123).
The default initialization for an int type is to initialize it to 0.
This is true of most (if not all) primitive types: char will initialize to (char)0 (or '\0' if you prefer), float will initialize to 0.0f, and any pointer initializes to NULL. For other types, the parameterless constructor is invoked.
In general, the default initialization should happen pretty much whenever you aren't able to specify a constructor (or choose not to).