How can I get the memory address of a constant variable in c++. When I try to get this I get an error.
int const nValue = 5;
int * pnPtr = &nValue;
The error message is given below. I'm using visual studio 2010.
Error 1 error C2440: 'initializing' : cannot convert from 'const int *' to 'int *'
Is there any method to do this?
"Is there any method to do this?"
Sure. You need a const int* pointer to get this address, as the error message says:
int const nValue = 5;
const int * pnPtr = &nValue;
// ^^^^^
An int* pointer would allow to modify the nValue, which is not legal, and that's why the compiler complains.
As for your comment. A const int* can be used to point to a regular int and a const int. The point is just you can't use it to modify the underlying memory at the address it holds.
The pointer variable itself isn't const and can be changed to a different address.
If you want both attributes you'll need to write:
const int const * pnPtr = &nValue;
// ^ ^
// | + prevents changing the pointer after initialization
// +- prevents changing the underlying memory
You need to use a pointer to a const int value like this:
int const *ptr = &nValue;
C++ is strict regarding const-correctness, and this is a good thing.
Related
This question already has answers here:
What is the difference between const int*, const int * const, and int const *?
(23 answers)
Closed last year.
I have a program like below and expect that:
with function void myFunc1 ( const int *x) ==> I cannot change the value of at the memory location that x points to, but can change the memory location that x points to.
with function void myFunc2 ( int const *x) ==> I cannot change the location that x points to as it is a const pointer. But I could change the value at the memory location that x points to.
However, upon compiling the code, I don't see the difference between const int *x vs int const *x:
in both function, the lines *x=8 in both function return error. I didn't expect error from myFunc2 because it is a const pointer, not a pointer to a const value.
in myFunc1, I expected to see value 5 after myFunc1 is close.
Could the experts here explain my 2 unexpected results above ? Here is my code:
#include "stdio.h"
int a = 5; // declared a global,
void myFunc1 ( const int *x) { // const parameter: pointer to a const int value.
// *x= 8; // error: assignment of read-only location ‘* x’ ==> cannot change the value at the location pointed by pointer. This is expected
printf("%d \n ", *x);
x = &a; // can change where the pointer point to.
// a is global and is not loss after closing myFunc2
printf("value in myFunc1: %d \n ", *x);
}
void myFunc2 ( int const *x) { // const parameter: const pointer, cannot change the address that x points to.
// *x= 8; // error: assignment of read-only location ‘* x’
printf("%d \n ", *x);
x = &a; // no compiling error here. This is not expected.
printf("value in myFunc2: %d \n ", *x);
}
int main() {
int *y;
int z = 6;
y = &z;
printf("value before myFunc1: %d \n", *y);
myFunc1(y);
printf("value after myFunc1: %d \n", *y); // expect to print 5. Result: print 6.
printf("value before myFunc2: %d \n", *y);
myFunc2(y);
printf("value after myFunc2: %d \n", *y); // expect to print 8 if the line *x=8 could be compiled . Result: print 6.
return 1;
}
I don't see the different between having 2 parameters (const int *x) vs (int const *x):
That's because int const* and const int* are the same thing.
If you want to make the pointer const, you have to put a const on its right, like this: int * const, a constant pointer to (non-constant) integer.
Unrelated (is it?) note on East const
I am one of those in favour of the so called East const, which means I prefer writing the const always on the right of what it applies to. For instance,
for a "pointer to constant int", I write int const *,
for a "constant pointer to constant int", I write int const * const.
As you see, the sentences in quotes map to the types if you read them right-to-left:
// 1 2 3 4 4 3 2 1
int const * const // constant pointer to constant int
Furthermore, always thinking of const as something that can be put on the right of what it applies to has also other advantages, sometimes in terms of peculiarities of the language that you can discover.
For instance, the following is how I discovered something more about references.
Take the declaration of a function parameter taken by reference to constant: int const& p. If you write it like this and think of it the East const way, it is clear that it declaring a p which is a reference to a constant int, not a constant reference to int.
After all, thinking East const, what would a constant reference to int look like? It'd be int & const, with the const on the right of what we'd like it to apply to, the reference &. However, this syntax is incorrect.
Why is that? Why can't I make a reference constant? Because it always is, as references cannot rebind. The standard simply doesn't let you write something totally redundant as a const applied to a reference.
Is it possible to typecast struct pointer into char pointer reference? I know that we can cast any pointer type to any other pointer type. But I got an error when I tried to typecast structure. I am using C++ compiler.
Error :
error: invalid initialization of non-const reference of type 'char*&' from a temporary of type 'char*'
Please see below example:
struct test {
int a;
bool y;
char buf[0];
}
struct test *x_p = NULL;
char *p = "Some random data......"; // this can be more than 64 bytes
x_p = (struct test *) malloc(sizeof(struct test) + 65);
x_p->a = 10;
x_p->y = false;
memcpy(x_p->buf, p, 64); //copy first 64 bytes
/* Here I am getting an error :
* error: invalid initialization of non-const reference of type 'char*&' from a temporary of type 'char*'
*/
call_test_fun((char *)x_p);
// Function Declaration
err_t call_test_fun(char *& data);
The function declaration should be:
err_t call_test_fun(char * data);
you had an erroneous & . The function definition should match.
Note that your code uses techniques that are not part of Standard C++: having a zero-sized array in a struct, and writing directly into malloc'd space. Maybe you are using a compiler with those things as extensions but it will be frowned on by many people as being prone to error. There is undoubtedly a better way to do whatever it is you are trying to do.
This question already has answers here:
how to avoid changing value of const in C
(4 answers)
Closed 8 years ago.
In an interview, I was asked to change constant value in CPP, but I said in CPP it is not possible but in c it is possible using pointer.
Interviewer said that using CPP it is possible and asked me to try but I couldn't and I came back to my room and tried again but what I figured out that I was able to change in C but same code was getting error when compiled as C++.
#include<stdio.h>
main()
{
const int i=5;
int *p;
p=&i;
*p=8;
printf("%d",i);
}
This code is changing the constant value of i in c but when I compile in CPP then
I get an error:
invalid conversion from 'const int*' to 'int*'
Given your error, the actual program must have been the following:
#include<stdio.h>
main()
{
const int i=5;
int *p;
p=&i;
*p=8;
printf("%d",i);
}
This produces a warning with gcc:
warning: assignment discards 'const' qualifier from pointer target type
and an error with g++:
error: invalid conversion from 'const int*' to 'int*'
So, let's change the title of your question to a better one:
Why does C allow conversion from const int * to int *, but C++ doesn't?
The reason why one gives a warning and another gives an error is not because one allows you to discard const qualifier and the other doesn't. It's merely because the C standard leaves such incorrect actions as undefined behavior, while the C++ standard specifically marks it as an error. Either way, doing this is wrong.
You can read this similar question asking why this is possible in C.
What I think interviewer wanted this:
int n = 0;
int const *p = &n;
The expression &n has type “pointer to int.” The declaration for p converts &n to type “pointer to const int,” adding a const qualifier in the process. This is a valid qualification conversion. This conversion in no way invalidates n’s declaration. The program can still use n to alter the int object, even if it can’t use *p for the
same purpose.
*p = 5; // wrong
But
n = 5; // OK
now *p is 5 although it is const type!
Now try to run this code in GCC or g++, it will work:
#include<stdio.h>
int main()
{
int n = 0;
const int *p;
p=&n;
printf("%d\n",*p);
n = 5;
printf("%d\n",*p);
return 0;
}
EDIT: The only way to change the value of const qualified object in C and C++ both is, change the value in the initialization statement:
const int i = 5 ---> const int i = 8
This is why const_cast exists, I believe the interviewer asked this because they have to deal with poorly designed library code they have no control over, however normally you shouldn't have to resort to using it in production.
If I do the following all is ok:
char* cp = "abc";
void* vp = NULL;
vp = static_cast<void*>(cp);//ok
cp = static_cast<char*>(vp);//ok
But the following is not:
char** cpp = &cp;
void** vpp = NULL;
vpp = static_cast<void**>(cpp);//error C2440: 'static_cast':
//cannot convert from 'char **' to 'void **'
cpp = static_cast<char**>(vpp);//error C2440: 'static_cast':
//cannot convert from 'void **' to 'char **'
Please can someone explain to me why the second examples are not allowed. Please don't quote the C++ standard as your whole answer, because I've already seen answers that quote it, and I don't understand what they meant. I want to understand why the second examples don't work (ie. if you could give an example where it would be dangerous that would be a great help). Because I don't get it. To me, both examples are casting pointers. Why does an additional level of indirection make any difference?
A void * pointer can point at "anything", and it is valid to convert all pointers to a void *, and it is valid to convert all pointers from void * to some other type.
However, a void ** is a pointer that points to a void * value. And a char ** is a pointer that points to char * value. These types don't point to the types that are convertible from one another. You can, if you NEED to do this, use void **vpp = reinterpret_cast<void **>(cpp);, but it's "not safe" (you are basically telling the compiler "Look, I know what I'm doing here, so just do it", which may not do what you actually expected...)
The restriction is to avoid breaking the type system. The first conversion is fine:
type *p = ...;
void *vp = p;
While you are giving away the type, you cannot inflict too much damage to the original value without since there is little to be done with a void object and all changes to vp are local to the pointer and cannot affect p.
If the second case was allowed:
type **p = ...;
void **vp = p;
Then perfectly looking and correct code could break your application. For example:
int *parray[10];
int **p = parray;
void **vp = p;
*vp = new double(); // now parray[0] is a pointer to a double object,
// not a pointer to an int!!!
The type system has been subverted.
That is, the problem is that in the second case there are operations that can be applied to the destination pointer that can modify the original object and cause bugs. Similar examples can be found with const other cases (you can convert int* to const int*, but you cannot convert int** to const int**...).
The const modifier in C++ before star means that using this pointer the value pointed at cannot be changed, while the pointer itself can be made to point something else. In the below
void justloadme(const int **ptr)
{
*ptr = new int[5];
}
int main()
{
int *ptr = NULL;
justloadme(&ptr);
}
justloadme function should not be allowed to edit the integer values (if any) pointed by the passed param, while it can edit the int* value (since the const is not after the first star), but still why do I get a compiler error in both GCC and VC++?
GCC: error: invalid conversion from int** to const int**
VC++: error C2664: 'justloadme' : cannot convert parameter 1 from 'int **' to 'const int **'. Conversion loses qualifiers
Why does it say that the conversion loses qualifiers? Isn't it gaining the const qualifier? Moreover, isn't it similar to strlen(const char*) where we pass a non-const char*
As most times, the compiler is right and intuition wrong. The problem is that if that particular assignment was allowed you could break const-correctness in your program:
const int constant = 10;
int *modifier = 0;
const int ** const_breaker = &modifier; // [*] this is equivalent to your code
*const_breaker = & constant; // no problem, const_breaker points to
// pointer to a constant integer, but...
// we are actually doing: modifer = &constant!!!
*modifier = 5; // ouch!! we are modifying a constant!!!
The line marked with [*] is the culprit for that violation, and is disallowed for that particular reason. The language allows adding const to the last level but not the first:
int * const * correct = &modifier; // ok, this does not break correctness of the code