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.
Related
I have this old C - code that my compiler is warning me about (old C-style cast).
volatile uint32_t* map;
void** argForSomeAPIfunction = (void**)↦
How can I convert this to C++ cast style? I need to convert volatile uint32_t** to void**.
The reason why I need this is that there is a closed-source vendor API that expects me to pass a void** pointer. I cannot change that function signature. On the other hand, the vendor told me that I can access this map of registers, that are always 32-bit, using a pointer to uint32_t, and he provided me the working example in C-style, that used (void**)&. I tried this C-example and it's working fine.
Side note: This vendor API communicates with a PCIe card, via a custom kernel module. There are two options two read the internal memory of the PCIe card, using a safe API function that uses "ioctl" and built-in checks, or using an unsupervised access to this 32-bit register map, that is initialized by calling to API::InitializeRegisterMap((void**)&map);. This is done only once, at the very beginning of the program. After that, I access directly the memory using map[offset], where offset goes in steps of 4 bytes, instead of the supervised function API::ReadRegister(offset) that in some cases is slower and critically delays the data acquisition (while the card is doing other tasks). The computer does not change the register contents, it just reads those. The external independent card can change at any time the register content, which is why the keyword volatile was introducted in the example from the vendor, I believe.
If this is for initialization, then I guess what it does is fill in a void *, not anything else, i.e. as if in C++ you'd have a parameter of type void *&.
I believe it is intended to be used as
void *ptr;
if (API::InitializeRegisterMap(&ptr)) {
...
}
then afterwards you will take the value in ptr and convert that value to volatile uint32_t *map:
void *ptr;
volatile std::uint32_t *map;
if (API::InitializeRegisterMap(&ptr)) {
map = static_cast<std::uint32_t *>(ptr);
}
Most notably in C, as opposed to C++, this can be written completely castless, which should be considered a good sign.
Also, you want to avoid reinterpret_cast like the plague.
After several trial and error steps, I noticed that this cannot be done with a simple cast step, you need to concatenate two:
void** argForSomeAPIfunction = reinterpret_cast<void**>(const_cast<uint32_t**>(&map));
The inner one is needed to cast away the volatile-ness, the second one for converting from int to void.
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.
I understand the use of pointer to constant for strlen implementation.
size_t strlen ( const char * str );
Can anyone suggest other reasons or provide some scenarios where 'Pointer to Const value' is useful in practice.
Think of it this way. You want me to look at the value of a variable but you don't want me to alter that variable in any way, so you pass it to me as a constant. When I use your function and see that a parameter is constant then I know there is a contract between you and I that says I should not change the value of that variable nor can I do it directly.
When you write code you don't always know who will use your functions. So it is good practice to protect your code. It also protects you from yourself, you will get compiler errors the moment you tr to change the value of that variable.
A side note: It is true that in C you can still change the value even though the parameter says const, but it would take another pointer which would alter the content of that variable in memory.
Try compiling this code and notice how the compiler protects you from making a mistake.
const char *cookies(const char *s)
{
return ('\0' == *s)? s: s + 1;
}
It won't let you compile, why? Because you are trying to change a const variable.
Another post with the same question here: const usage with pointers in C
Marking a pointer argument as const is a contract whereby you assert to the user you won't change the values pointed to. It's also a contract that you won't try to write to them, so that it is legal for them to give you a pointer to something that is read-only memory, and your function won't crash - as long as you fulfill this contract.
It's not just "useful", in some cases it is required, particularly when you are dealing with what amounts to write protected memory such as string literals or any value stored in the code section of your executable.
It's also valuable when you are using data that might be shared: If two threads want to call a function foo(char* x) each will need its own copy of the string, otherwise bad things would happen. If the function is foo(const char* x) then we know it is safe for both to share a single pointer to the input.
Consider, if you have a pointer to write-protected memory:
mprotect(ptr, sizeOfData, PROT_READ);
It is now not possible to call a function that attempts to write to ptr without a program exception (this is often done with things like caches when nobody owns a write-lock on the cache).
Thus you can only call const functions on ptr at this point.
Pointer to const of char is the type of the strings literals (those inside ""). This is the primary use for pointer to const value.
I had a trouble with my own const attribute. I could not protect my const data completely because of functions. Functions can modify everything.
const reference is an awful thing because it requires an address; if it's an address of a const variable, most likely the variable data still can be changed or modified. My data is writeable. The parser cannot prevent (ignore) this kind of code because it's totally legal in C++.
scanf("%d", &const_var);
How to lock my data and make my const data unmodifiable (or unwritable)?
In this case...
scanf("%d", &foo); // Out of range!!!
...foo could indeed be modified, or pretty much anything else can happen. The compiler can't catch this because scanf uses old-fashion c varargs which allows any number of parameters, of any type to be passed, with no checking whatsoever. There is no attempt to ensure that the parameter passed is an address, let alone the address of an int, and certainly not the address of a non-const int.
For safer C++ code, avoid using printf/sscanf family of functions entirely.
Lint or some other source code checker could help here. I haven't tried it with this specific case.
C++ is not a safe language. In C++, you can only protect yourself from accidents, not perfidy. If a user wants to change something that they're not supposed to be able to change, it's as simple as this:
void SomeFunc(const Obj &dontChange)
{
Obj &change = const_cast<Obj &>(dontChange);
change.X = ...;
}
There is nothing you can do to protect yourself from a user who is determined to violate the contract between your code and theirs. You can only protect yourself from a user who accidentally tried to break the contract. You can't even protect private members of your class, as they can simply cast the type to something else and poke at the memory directly.
Your best bet is this: don't worry about it. If the user does the wrong thing with some variable, then any breakage that happens as a result is their fault.
You can't protect yourself from such situations directly. If the constant is put inside writable memory, one may always acquire address of this constant and modify it one or another way. Remember though, that standard says, that modifying constant values is considered to have an undefined behavior.
If you want the constant to be unmodifyable, you can make a workaround and use a macro:
#define foo 100
This is a trick, because it will exchange all occurrences of foo in the source into 100, however noone will be able to modify its value in the runtime (by definition, 100 is 100).
However, I would avoid using macros. You may use another workaround instead: define a function:
constexpr int FooValue()
{
return 100;
}
Noone will be able to modify it either, but this solution allows you to embed such "constant" in class or namespace. If you use compiler, which can handle C++11, using constexpr will allow you to input this function everywhere, where you might have inserted a constant, for example:
int array[FooValue()];
i'm pretty new to box2d and i'm trying to use the userdata (of type void*) field in the b2body object to store an int value (an enum value, so i know the type of the object).
right now i'm doing something this:
int number = 1023;
void* data = (void*)(&number);
int rNumber = *(int*)data;
and i get the value correctly, but as i've been reading around casting to void* it's not portable or recommendable... is my code cross-platform? is it's behavior defined or implementation dependent?
Thanks!
Casting to void * is portable. It is not recommended because you are losing type safety. Anything can be put into a void * and anything can be gotten out. It makes it easier to shoot yourself in the foot. Otherwise void * is fine as long as you are careful and extra cautious.
You are actually not casting int to void*, you cast int* to void*, which is totally different.
A pointer to any type can be stored in a void*, and be cast back again to the same type. That is guaranteed to work.
Casting to any other type is not portable, as the language standard doesn't say that different pointers have to be the same size, or work the same way. Just that void* has to be wide enough to contain them.
One of the problems with void* is that you need to know (keep track of) what type it originally was in order to cast it properly. If it originally was a float and you case it to an int the compiler would just take your word for it.
To avoid this you could create a wrapper for your data which contains the type, that way you will be able to always cast it to the right type.
Edit: you should also make a habit of using C++ casting style instead of C i.e. reinterpret_cast
void * is somehow a relic of the past (ISO C), but very convenient. You can use it safely as far as you are careful casting back and forward the type you want. Consider other alternatives like the c++ class system or overloading a function
anyways you will have better cast operators, some times there is no other way around (void*), some other times they are just too convenient.
It can lead to non portable code, not because of the casting system, but because some people are tempted to do non portable operations with them. The biggest problem lies in the fact that (void*) is a as big as a memory address, which in many platforms happens to be also the length of the platform integers.
However in some rare exceptions size(void*) != size(int)
If you try to do some type of operations/magic with them without casting back to the type you want, you might have problems. You might be surprised of how many times I have seen people wanting to store an integer into a void* pointer
To answer your question, yes, it's safe to do.
To answer the question you didn't ask, that void pointer isn't meant for keeping an int in. Box2D has that pointer for you to point back to an Entity object in your game engine, so you can associate an Entity in your game to a b2Body in the physics simulation. It allows you to more easily program your entities interact with one another when one b2Body interacts with another.
So you shouldn't just be putting an enum in that void*. You should be pointing it directly to the game object represented by that b2body, which could have an enum in it.