The address of const variable, C++ - c++

Recently I was rereading the Effective C++ by Scott Meyers (3-rd edition). And according to Meyers:
"Also, though good compilers won’t set
aside storage for const objects of integral types (unless you create a
pointer or reference to the object), sloppy compilers may, and you may
not be willing to set aside memory for such objects."
Here in my code I can print the address of const variable, but I have not created a pointer or reference on it. I use Visual Studio 2012.
int main()
{
const int x = 8;
std::cout<<x<<" "<<&x<<std::endl;
}
The output is:
8 0015F9F4
Can anybody explain my the mismatch between the book and my code? Or I have somewhere mistaken?

By using the address-of operator on a variable, you are in fact creating a pointer. The pointer is a temporary object, not a declared variable, but it's very much there.
Furthermore there is a declared variable of pointer type that points to your variable: the argument to the overloaded operator << that you used to print the pointer.

std::cout<<x<<" "<<&x<<std::endl;
You tried to get the address of the variable x,so the compiler thinks it is necessary to generate codes to set aside storage for const objects.

By &x, you ODR-used the variable, which makes allocating actual storage for x necessary.

A good compiler (when using optimizations) will try to replace any compile-time constant by its value in your code to avoid making a memory access. However, if you do request the address of a constant (like you do) it can't do the optimization of not allocating memory to it.
However, one important thing to note is that it doesn't mean the research and replace wasn't done in your code. As you are not supposed to change the value of the constant, the compiler will assume it is safe to do a "research and replace" on it. If you do change the value with a const_cast you will get undefined behavior. It tends to work fine if you compile in debug but usually fails if your compiler optimizes the code.

In C++,for basic data type constants, the compiler will put it in the symbol table without allocating storage space, and ADT(Abstract Data Type)/UDT(User Defined Type) const object will need to allocate storage space (large objects). There are some cases also need to allocate storage space, such as forcing declared as extern symbolic constants or take the address of symbolic constants,etc.

Related

I'm changing the value of a const variable by accessing the memory location. Why doesn't it work?

I am trying to understand const in c++.
I wrote this following code snippet:
const int x=5;
int *ptr;
ptr=(int*)&x;
cout<<"address of x="<<&x<<endl;
cout<<"value of ptr="<<ptr<<endl;
*ptr=11;
cout<<"*ptr="<<*ptr<<endl;
cout<<"x="<<x;
The output is
address of x=0x28fef8
address of ptr=0x28fef8
*ptr=11
x=5
Since ptr is pointing to x, i was sure the value of the *ptr and x would be the same.
Why are the values different?
I understand that x is const, however, i am changing the value at the memory address by doing *ptr .
Please tell me what am i missing.
Your C style cast is removing the constness, making the assignment possible. After that you write to a value declared const. This invokes undefined behavior and afterwards everything goes. This also means that there is no way to explain the output your are seeing. Most likely the compiler assumed the value never changes and just used constant folding, hence you get x=5, but we will never know for sure.
The take-away: C-style casts are evil and almost never needed.
Official answer (according to the C++ language standard):
Undefined behavior.
Practical answer (depending on compiler implementation):
With a global const int x=5, the variable is allocated in the RO-data section of the executable image.
The result of executing *ptr=11 will therefore be an illegal memory access exception during runtime.
With a local const int x=5, the variable is allocated on the (RW) stack section of the executable image.
But since x is constant, the compiler replaces every r-value reference of this variable with the value of 5.
"const" tells the compiler, if anyone writes code that tries to modify this object/variable then throw a compile error to prevent them from doing so, and by the way you are free to do any optimization assuming that the value did not change in this context. A C style cast / const_cast says, I know what I am doing, don't bother throwing errors at me as I am going to do it anyway. So by doing both you are living dangerously. Sometimes your get away with it, sometimes the system gets you. Whether variables placed in .rodata cause exceptions when you try to write is platform dependent. If you do not have hardware memory protection and all your code runs from RAM, then you can pretty much write where you want, including overwrite code (.text). For me the beauty of const is that it is infectious (others have called it evil or messy just because of this ).

In C++ are all names essentialy "under-the-hood" pointers?

In C++ are names actually pointers-under-the-hood? For example:
// num is a name that points to the address of the
// memory location containing 32.53
double num (32.53);
*num; // so can we deference it and get 32.53?
num; // same as *num but the compiler automatically
// dereferences the name for us?
Clarification:
This question was kind of an odd mix of "What's happening at the machine level?" and also about the C++ language semantics of pointers. Thus, I can see why the answers are yes/no. "Yes" because outside of the language semantics, an identifier could be thought of as referring to a location in memory; and "No" because that is still not a C++ pointer and it is incorrect to deference a non-pointer double as shown in the code.
So I think both camps have successfully answered my question. It could perhaps be restated as, "Since names refer to memory locations, why can't they be treated as implicit pointers?" But such a question might generate fuzzy debates or just not be worth answering. I will carefully go over the answers and try to find the one that (I feel) answers the question the best from both angles. In other words, one that doesn't just say "That's not a C++ pointer dummy!" or "of course the name points to memory somehow".
A pointer is a programmer-visible value which holds the location of some object (or else a null value that doesn't point to an object, or an indeterminate value).
Although addressing is involved in resolving name references at run-time, names of variables are not pointers in C++. This is because variable names are not run-time values which represent locations; they are compile-time (and in the case of external names with linkage, link-time) symbols that denote locations.
"Pointer" and "address" are not the same thing. For instance, when we call a function, assuming it is not tail-call optimized or inlined, typically a "return address" is stored somewhere so that the function can return to the caller. This address is not a pointer; or at least not a C++ pointer. It is a "no user serviceable component" managed behind the scenes by the implementation, just like the stack pointer (if there is such a thing), stack frame pointer and other machine-level features. C++ references, at least in some cases, are also implemented using run-time addresses. C++ references are also not pointers.
There is a run-time pointer value associated with a variable name, and you can access this property using the address-of operator:
double *pnum = &num;
but not like this:
*num; // so can we deference it and get 32.53?
Have you tried it? The unary dereference operator requires an expression of pointer type; it won't work with an expression of type double. (It can work with an expression of class type, if suitably overloaded, which is something else.)
Though by means of the & operator we can get a pointer to the storage location named by num, the name num itself isn't that pointer.
When we evaluate code like num = 3, quite likely an address is involved. Or maybe not. For instance, if num is optimized into a register, then this just loads 3 into that register. Even if num has a memory address, that address is not programmer-visible in that situation. Pointers are programmer-visible: the programmer creates them, displaces them, dereferences them, stores them in variables, passes them into functions, and so on.
In fact a name isn't anything in C++; names need not be retained at run time and are not accessible in any portable way. (Implementations have ways of retaining information about names after compilation, for the sake of symbolic debugging, and platforms that support dynamic linking have ways of looking dynamic symbols from strings.)
If you extend the definition of pointer to "any conceptual device that refers to some information in memory" then, yes, absolutely.
However, nobody does.
You'd be closer to the money if you used the term handle which has, variably, been used to mean "pointer", "reference", "variable", "resource object", "name" in source code, "accessor", "identifier", and myriad other things.
One generally comes to the conclusion that general terms are too ambiguous, and end up sticking with terms that are either language-specific (such as C++'s "pointer", with its very specific semantics, not including those which you have posited), or unambiguous and commonly accepted across the realm of the industry. There are very few of those.
No.
From the definition of pointer type of the C standard (at §6.2.5/20):
A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type.
(emphasis mine).
In your case:
double num (32.53);
you have a double, with identifier num, whose value is 32.53, which is not intended to use as a pointer value. Not even the type of num is a pointer type.
Therefore no, num is not a pointer and as the compiler would have told you, if you had tried to compile:
*num;
you can't dereference it.
No.
In this case, num is the name of an object of type double. Its declaration does not explicitly or implicitly create a pointer. It creates a floating-point object, initialized to 32.53.
You can obtain a pointer value (not a pointer object) by taking the address of the object, as in&num, but you can that for any object.
As for *num, that's illegal if num is of type double.
The name of an object is something that refers to the object itself; in that sense, if I squint really hard, I can think of that as a kind of "pointer". But a pointer in the C++ sense is a value or object containing a memory address, and it exists while the program is executing; an identifier exists only in the C++ source code. A C++ compiler will have some internal compile-time data structure that refers to a declared variable, that will include (or refer to) information about its name and type, but IMHO it's not reasonable to call that data structure a "pointer". It's likely to be something far more complex than a memory address. And the name of a variable declared inside a function will refer to different objects, or to none at all, at different times during the execution of the program.
Yes, in the sense that, like a pointer, an identifier is a handle for an object, and not the object itself. But it is still one fewer level of indirection than a pointer variable (whose name is a handle to the address which is a handle to the object).
In fact, the compiler will maintain a symbol table which is a mapping from identifier to location of the object (here location is typically not memory address, but offset from the bottom of the stack, or from the beginning of the data segment -- but then again C++ pointers aren't physical addresses either on virtual memory systems) Normally this symbol table is output by the compiler for use during debugging. Dynamic languages would actually use the symbol table during execution, to support late-binding and eval(). But C++ doesn't use identifiers at runtime.
I think variables in assembly work like that, i.e. that a name is actually a human-readable label for an address. (This article would indicate so, at least: http://www.friedspace.com/assembly/memory.php ) In C/C++, however, the name of the variable is actually a dereferenced address. To get the address, you have to use the & operator.
Pointers in C/C++ are actually variables that contain an address--something that most likely has its own address (though it doesn't need to if the compiler chooses to store the pointer in a CPU register and you don't try to get its address--if you do, then, you're guaranteed to get one).
What you're talking about really comes down to the definition of an "lvalue".
Let's consider a simple variable like you gave in the question:
double num = 32.53;
num is an lvalue, which roughly translates to the fact that it refers to some location in memory.
When it's used in an expression, an lvalue can be converted to an rvalue, which translates (roughly) to retrieving the value from that memory location. For example, given an expression like:
num = num + 1.5;
num starts out as an lvalue, but where it's used on the right side of the assignment, it's converted to an rvalue. That basically means the value from that location in memory is fetched, then 1.5 is added to it, then the resulting value is written back to the location in memory that num refers to.
That does not, however, mean that num is a pointer. num does refer to a location in memory. A pointer is different: it's a variable that refers to some other location in memory. A pointer variable is itself an lvalue. It has a location in memory, and its name refers to that location in memory. The value stored in that location in memory, however, is itself a reference to some location in memory (normally some location other than the pointer itself).
Perhaps a picture would help:
Here I'm using a solid arrow-line to indicate an association that can't be changed. The rectangles stand for the names of variables, and the sideways diamonds to memory locations. So, num is immutably associated with one location in memory. It can't be modified to refer any other location, and it can't be dereferenced.
If we define something like:
double num2 = 12.34;
double *ptr = &num2;
Then we get roughly the situation depicted in the second part of the picture. We've defined num2 as a double, just like num is (but holding a different value). We've then defined a pointer (named pointer) that points to num2. In other words, when we dereference pointer, we get num2. The connection from pointer to num2 is a dashed line though--indicating that if we chose to, we could change this--we could assign the address of some other double to pointer, which would make pointer refer to that other variable's location.
Though you haven't asked about it (yet) the third part of the picture shows what we'd get if we defined something like:
double num3 = 98.76;
double &reference = num3;
In this case, we've created a third object in memory (num3), and we've created a reference (named reference) that refers to num3. I've drawn the location for reference in a lighter color to signify the fact that there may or may not be an actual location in memory used to store the reference itself--it could just be a second name that refers (more or less) directly to the num3. Unlike the pointer, this has a solid line from the reference to the object to which it refers, because it can't be changed--once the reference is created, it always refers to that same location.
To answer your other question, with a definition like you gave (double num = 32.53;), no you cannot dereference num. An expression like *num = 10.2; simply won't compile. Since the name of the variable always refers to that variable's location, trying to use * to refer to its location simply isn't necessary, supported, or allowed.
No. The value num is probably stored in a register, for such a simple example. And on todays CPU's, registers do not have an address.
num is a name of an object. C++ pretends that the object lives at a specific place in memory, but that's not very efficient on modern architectures. Most operations require the value to be in a register, so if the compiler can keep it in a register it will. If not, the compiler may benefit from putting the value in a cache-friendly location. This may not be the same location every time, so value may move around in memory.
So, the name is far more powerful that a pointer: it follows the value as it moves around in memory. Creating and storing a pointer &num disallows such movements, as moving num would then invalidate the pointer.

Compiler ignores code returning a local char* from a function

As far as I know the following code is bad. But, Visual Studio 2010 doesn't give me any warning.
char* CEmployee::GetEmployeeName()
{
char* szEmployeeName = "";
CEmployeeModel* model = GetSwitchMod();
if (model != NULL)
{
szEmployeeName = model->GetName();
}
return szEmployeeName;
}
It's not the compiler's job to debug your code.
lint or similar static checker might find this. Try running Code Analysis if you have one of the premium VS versions that includes it. Make sure you build with /W4 and fix all warning errors.
You're not returning a reference to a local variable, as you're returning by value, so the local variable — the pointer — is copied.
Don't confuse the pointer with its pointee.
If anything, you'd be returning a dangling pointer (though in practice the string literal buffer is likely to be in static memory somewhere). Dangling pointers don't tend to be diagnosed at compile-time.
If model->GetName() returns a dynamically-allocated buffer, making the pointer no longer point to the string literal, then your code is fine.
TRWTF is that you didn't write char const* szEmployeeName = "". Leaving out the const has been deprecated for over a decade, and is illegal in C++0x. It's a concern that so many people are still doing this.
It's even worse that there are still people using char* for strings, instead of std::string.
Returning szEmployeeName here is actually not an error - the string is allocated statically in read-only memory (the .rodata section in ELF executables). Quoting the (C++03) Standard:
2.13.4.1
An ordinary string literal has type
“array of n const char” and static
storage duration (3.7), where n is the
size of the string as defined below,
and is initialized with the given
characters.
3.7.1
All objects which neither have dynamic
storage duration nor are local have
static storage duration. The storage
for these objects shall last for the
duration of the program
On the other hand, trying to modify this string results in undefined behaviour - in this particular case, you'll most likely get a crash at runtime. szEmployeeName should be really declared as const char* (and there are historical reasons why the standard allows initializing a plain char * with a string literal). Again, quoting the Standard:
2.13.14.2
The effect of attempting to modify a
string literal is undefined.
You're returning a pointer to a char at the end. Are you sure the memory that the pointer is referring to is still active when the code leaves the function* (what is the lifetime of model->GetName()'s return)
*EDIT: "loop" is wrong.
This code isn't necessarily "wrong" in all cases. If the thing pointed to by the pointer returned from GetName is still alive, and the pointer returned from GetEmployeeName is not written to then the code appears to be well-formed. The compiler can't reasonably be expected to do a full analysis of all your code to tell you if there's an actual problem with your pointer manipulation.
You should be using std::string as #Tomalak Geret'kal noted in his answer. That then resolves all these lifetime issues.
There's a certain point at which you should be able to say "Why am I writing code this way???" and the compiler isn't going to go to extra-ordinary lengths to warn you about every possible undefined behavior in your program (it's undefined for a reason).
This code is fine. There's nothing going on here that could possibly cause the target of szEmployeeName to be freed.
If model is NULL, then you return a pointer to "". Using a non-const pointer certainly is questionable, but the string literal "" survives for the lifetime of your program, it's not an error to return it.
If model is non-null, you return the pointer returned by model->GetName(). Since CEmployee::GetEmployeeName() doesn't free any memory, the pointer is just as valid when returned as it was when you got it from model->GetName(). Specifically, either the pointer is valid, or it is a dangling pointer, indicating a bug in CEmployeeModel->GetName().
There are no circumstances where CEmployeeModel::GetName() is correct but CEmployee::GetEmployeeName returns a bad pointer.

const variable in c++

these are the some silly question ..i want to ask..please help me to comprehend it
const int i=100; //1
///some code
long add=(long)&i; //2
Doubt:for the above code..will compiler first go through the whole code
for deciding whether memory should be allocated or not..or first it ll store the
variable in read only memory place and then..allocate stroage as well at 2
doubt:why taking address of variable enforce compiler to store variable on memory..even
though rom or register too have address
In your code example, add contains the address, not the value, of i. I believe you may have thought that i was not stored in normal memory unless/until you take its address. This is not the case.
const does not mean the value is stored in ROM. It is stored in normal memory (often the stack) just like any other variable. const means the compiler will go to some lengths to prevent you from modifying the value.
const is not, and was never intended, to be some sort of security mechanism. If you obtain the address of the memory and want to modify it, you can do so. Of course this is almost always a bad idea, but if you really need to do it, it is possible.
I never wrote a compiler implementing this, but I think that it would be simple to just handle the variable as a normal variable but using the constant value where the variable value is used and using the address of the variable if the address is used.
If at the end of the scope of the variable no one took the address then I can just drop it instead of doing a real allocation because for all other uses the constant value has been used instead of compiling a variable loading operation.
constant values (not the only use for const, but the one used here) are not 'stored in normal memory' (nor in ROM, of course). the compiler simply uses the value (100 in this case) whenever the code uses the variable.
Of course, if the value isn't stored anywhere, there's no meaning of an address for the constant.
Other uses of const are stored in 'normal memory', and you can take their address, but the result is a 'pointer to const value', so it's (in principle) unusable for modification of the value. A hard cast would of course change that, so they trigger a nasty compiler warning.
also, remember that the C/C++ compiler operates totally at compile time (by definition!), it's nothing unusual that some use at a later part affects the code generation of an early part.
A very obvious example is the declaration of stack variables: the compiler has to take into account all the variables declared at any given level to be able to generate the stack allocation at the block entry.
I am a little confused about what you are asking but looking at your code:
i = 100 with a address of 0x?????????????
add = whatever the address is stored as a long int
There is no (dynamic) memory allocation in this code. The two local variables are created on stack. The address of i is taken and brutally cast into long, which is then assigned to the second variable.

What use are const pointers (as opposed to pointers to const objects)?

I've often used pointers to const objects, like so...
const int *p;
That simply means that you can't change the integer that p is pointing at through p. But I've also seen reference to const pointers, declared like this...
int* const p;
As I understand it, that means that the pointer variable itself is constant -- you can change the integer it points at all day long, but you can't make it point at something else.
What possible use would that have?
When you're designing C programs for embedded systems, or special purpose programs that need to refer to the same memory (multi-processor applications sharing memory) then you need constant pointers.
For instance, I have a 32 bit MIPs processor that has a little LCD attached to it. I have to write my LCD data to a specific port in memory, which then gets sent to the LCD controller.
I could #define that number, but then I also have to cast it as a pointer, and the C compiler doesn't have as many options when I do that.
Further, I might need it to be volatile, which can also be cast, but it's easier and clearer to use the syntax provided - a const pointer to a volatile memory location.
For PC programs, an example would be: If you design DOS VGA games (there are tutorials online which are fun to go through to learn basic low level graphics) then you need to write to the VGA memory, which might be referenced as an offset from a const pointer.
-Adam
It allows you to protect the pointer from being changed. This means you can protect assumptions you make based on the pointer never changing or from unintentional modification, for example:
int* const p = &i;
...
p++; /* Compiler error, oops you meant */
(*p)++; /* Increment the number */
another example:
if you know where it was initialized, you can avoid future NULL checks.
The compiler guarantees you that the pointer never changed (to NULL)…
In any non-const C++ member function, the this pointer is of type C * const, where C is the class type -- you can change what it points to (i.e. its members), but you can't change it to point to a different instance of a C. For const member functions, this is of type const C * const. There are also (rarely encountered) volatile and const volatile member functions, for which this also has the volatile qualifier.
One use is in low-level (device driver or embedded) code where you need to reference a specific address that's mapped to an input/output device like a hardware pin. Some languages allow you to link variables at specific addresses (e.g. Ada has use at). In C the most idiomatic way to do this is to declare a constant pointer. Note that such usages should also have the volatile qualifier.
Other times it's just defensive coding. If you have a pointer that shouldn't change it's wise to declare it such that it cannot change. This will allow the compiler (and lint tools) to detect erroneous attempts to modify it.
I've always used them when I wanted to avoid unintended modification to the pointer (such as pointer arithmetic, or inside a function). You can also use them for Singleton patterns.
'this' is a hardcoded constant pointer.
Same as a "const int" ... if the compiler knows it's not going to change, it can be optimization assumptions based on that.
struct MyClass
{
char* const ptr;
MyClass(char* str) :ptr(str) {}
void SomeFunc(MyOtherClass moc)
{
for(int i=0; i < 100; ++i)
{
printf("%c", ptr[i]);
moc.SomeOtherFunc(this);
}
}
}
Now, the compiler could do quite a bit to optimize that loop --- provided it knows that SomeOtherFunc() does not change the value of ptr. With the const, the compiler knows that, and can make the assumptions. Without it, the compiler has to assume that SomeOtherFunc will change ptr.
I have seen some OLE code where you there was an object passed in from outside the code and to work with it, you had to access the specific memory that it passed in. So we used const pointers to make sure that functions always manipulated the values than came in through the OLE interface.
Several good reasons have been given as answers to this questions (memory-mapped devices and just plain old defensive coding), but I'd be willing to bet that most instances where you see this it's actually an error and that the intent was to have to item be a pointer-to-const.
I certainly have no data to back up this hunch, but I'd still make the bet.
Think of type* and const type* as types themselves. Then, you can see why you might want to have a const of those types.
always think of a pointer as an int. this means that
object* var;
actually can be thought of as
int var;
so, a const pointer simply means that:
const object* var;
becomes
const int var;
and hence u can't change the address that the pointer points too, and thats all. To prevent data change, u must make it a pointer to a const object.