C/C++ changing the value of a const - c++

I had an article, but I lost it. It showed and described a couple of C/C++ tricks that people should be careful. One of them interested me but now that I am trying to replicate it I'm not being able to put it to compile.
The concept was that it is possible to change by accident the value of a const in C/C++
It was something like this:
const int a = 3; // I promise I won't change a
const int *ptr_to_a = &a; // I still promise I won't change a
int *ptr;
ptr = ptr_to_a;
(*ptr) = 5; // I'm a liar; a is now 5
I wanted to show this to a friend but now I'm missing a step. Does anyone know what's missing for it to start compiling and working?
ATM I'm getting invalid conversion from 'const int*' to 'int*' but when I read the article I tried and it worked great.

you need to cast away the constness:
linux ~ $ cat constTest.c
#include <stdio.h>
void modA( int *x )
{
*x = 7;
}
int main( void )
{
const int a = 3; // I promisse i won't change a
int *ptr;
ptr = (int*)( &a );
printf( "A=%d\n", a );
*ptr = 5; // I'm a liar, a is now 5
printf( "A=%d\n", a );
*((int*)(&a)) = 6;
printf( "A=%d\n", a );
modA( (int*)( &a ));
printf( "A=%d\n", a );
return 0;
}
linux ~ $ gcc constTest.c -o constTest
linux ~ $ ./constTest
A=3
A=5
A=6
A=7
linux ~ $ g++ constTest.c -o constTest
linux ~ $ ./constTest
A=3
A=3
A=3
A=3
also the common answer doesn't work in g++ 4.1.2
linux ~ $ cat constTest2.cpp
#include <iostream>
using namespace std;
int main( void )
{
const int a = 3; // I promisse i won't change a
int *ptr;
ptr = const_cast<int*>( &a );
cout << "A=" << a << endl;
*ptr = 5; // I'm a liar, a is now 5
cout << "A=" << a << endl;
return 0;
}
linux ~ $ g++ constTest2.cpp -o constTest2
linux ~ $ ./constTest2
A=3
A=3
linux ~ $
btw.. this is never recommended... I found that g++ doesn't allow this to happen.. so that may be the issue you are experiencing.

Note any attempt to cast away constness is undefined by the standard. From 7.1.5.1 of the standard:
Except that any class member declared
mutable can be modified, any
attempt to modify a const object
during its lifetime
results in undefined behavior.
And right after this example is used:
const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object
So in short what you want to do isn't possible using standard C++.
Further when the compiler encounters a declaration like
const int a = 3; // I promisse i won't change a
it is free to replace any occurance of 'a' with 3 (effectively doing the same thing as #define a 3)

Just a guess, but a common question is why one can't convert an int** to a const int**, which at first appears to be reasonable (after all, you're just adding a const, which is normally ok). The reason is that if you could do this, you could accidentally modify a const object:
const int x = 3;
int *px;
const int **ppx = &px; // ERROR: conversion from 'int**' to 'const int**'
*ppx = &x; // ok, assigning 'const int*' to 'const int*'
*px = 4; // oops, just modified a const object
It's a very non-intuitive result, but the only way to make sure that you can't modify a const object in this case (note how there are no typecasts) is to make line 3 an error.
You're only allowed to add const without a cast at the FIRST level of indirection:
int * const *ppx = &px; // this is ok
*ppx = &x; // but now this is an error because *ppx is 'const'
In C++, it is impossible to modify a const object without using a typecast of some sort. You'll have to use either a C-style cast or a C++-style const_cast to remove the const-ness. Any other attempt to do so will result in a compiler error somewhere.

Back in the mists of time, we paleo-programmers used FORTRAN. FORTRAN passed all its parameters by reference, and didn't do any typechecking. This meant it was quite easy to accidentally change the value of even a literal constant. You could pass "3" to a SUBROUTINE, and it would come back changed, and so every time from then on where your code had a "3", it would actually act like a different value. Let me tell you, those were hard bugs to find and fix.

Did you try this?
ptr = const_cast<int *>(ptr_to_a);
That should help it compile but it's not really by accident due to the cast.

In C++, Using Microsoft Visual Studio-2008
const int a = 3; /* I promisse i won't change a */
int * ptr1 = const_cast<int*> (&a);
*ptr1 = 5; /* I'm a liar, a is now 5 . It's not okay. */
cout << "a = " << a << "\n"; /* prints 3 */
int arr1[a]; /* arr1 is an array of 3 ints */
int temp = 2;
/* or, const volatile int temp = 2; */
const int b = temp + 1; /* I promisse i won't change b */
int * ptr2 = const_cast<int*> (&b);
*ptr2 = 5; /* I'm a liar, b is now 5 . It's okay. */
cout << "b = " << b << "\n"; /* prints 5 */
//int arr2[b]; /* Compilation error */
In C, a const variable can be modified through its pointer; however it is undefined behavior. A const variable can be never used as length in an array declaration.
In C++, if a const variable is initialized with a pure constant expression, then its value cannot be modified through its pointer even after try to modify, otherwise a const variable can be modified through its pointer.
A pure integral const variable can be used as length in an array declaration, if its value is greater than 0.
A pure constant expression consists of the following operands.
A numeric literal (constant ) e.g. 2, 10.53
A symbolic constant defined by #define directive
An Enumeration constant
A pure const variable i.e. a const variable which is itself initialized with a pure constant expression.
Non-const variables or volatile variables are not allowed.

Some of these answers point out that the compiler can optimize away the variable 'a' since it is declared const. If you really want to be able to change the value of a then you need to mark it as volatile
const volatile int a = 3; // I promise i won't change a
int *ptr = (int *)&a;
(*ptr) = 5; // I'm a liar, a is now 5
Of course, declaring something as const volatile should really illustrate just how silly this is.

this will create a runtime fault. Because the int is static. Unhandled exception. Access violation writing location 0x00035834.
void main(void)
{
static const int x = 5;
int *p = (int *)x;
*p = 99; //here it will trigger the fault at run time
}

You probably want to use const_cast:
int *ptr = const_cast<int*>(ptr_to_a);
I'm not 100% certain this will work though, I'm a bit rusty at C/C++ :-)
Some readup for const_cast: http://msdn.microsoft.com/en-us/library/bz6at95h(VS.80).aspx

const int foo = 42;
const int *pfoo = &foo;
const void *t = pfoo;
void *s = &t; // pointer to pointer to int
int **z = (int **)s; // pointer to int
**z = 0;

The article you were looking at might have been talking about the difference between
const int *pciCantChangeTarget;
const int ci = 37;
pciCantChangeTarget = &ci; // works fine
*pciCantChangeTarget = 3; // compile error
and
int nFirst = 1;
int const *cpiCantChangePointerValue = &nFirst;
int nSecond = 968;
*pciCantChangePointerValue = 402; // works
cpiCantChangePointerValue = &ci; // compile error
Or so I recall-- I don't have anything but Java tools here, so can't test :)

#include<iostream>
int main( void )
{
int i = 3;
const int *pi = &i;
int *pj = (int*)&i;
*pj = 4;
getchar();
return 0;
}

I was looking on how to convert between consts and I found this one http://www.possibility.com/Cpp/const.html maybe it can be useful to someone. :)

I have tested the code below and it successfully changes the constant member variables.
#include <iostream>
class A
{
private:
int * pc1; // These must stay on the top of the constant member variables.
int * pc2; // Because, they must be initialized first
int * pc3; // in the constructor initialization list.
public:
A() : c1(0), c2(0), c3(0), v1(0), v2(0), v3(0) {}
A(const A & other)
: pc1 (const_cast<int*>(&other.c1)),
pc2 (const_cast<int*>(&other.c2)),
pc3 (const_cast<int*>(&other.c3)),
c1 (*pc1),
c2 (*pc2),
c3 (*pc3),
v1 (other.v1),
v2 (other.v2),
v3 (other.v3)
{
}
A(int c11, int c22, int c33, int v11, int v22, int v33) : c1(c11), c2(c22), c3(c33), v1(v11), v2(v22), v3(v33)
{
}
const A & operator=(const A & Rhs)
{
pc1 = const_cast<int*>(&c1);
pc2 = const_cast<int*>(&c2),
pc3 = const_cast<int*>(&c3),
*pc1 = *const_cast<int*>(&Rhs.c1);
*pc2 = *const_cast<int*>(&Rhs.c2);
*pc3 = *const_cast<int*>(&Rhs.c3);
v1 = Rhs.v1;
v2 = Rhs.v2;
v3 = Rhs.v3;
return *this;
}
const int c1;
const int c2;
const int c3;
int v1;
int v2;
int v3;
};
std::wostream & operator<<(std::wostream & os, const A & a)
{
os << a.c1 << '\t' << a.c2 << '\t' << a.c3 << '\t' << a.v1 << '\t' << a.v2 << '\t' << a.v3 << std::endl;
return os;
}
int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
A ObjA(10, 20, 30, 11, 22, 33);
A ObjB(40, 50, 60, 44, 55, 66);
A ObjC(70, 80, 90, 77, 88, 99);
A ObjD(ObjA);
ObjB = ObjC;
std::wcout << ObjA << ObjB << ObjC << ObjD;
system("pause");
return 0;
}
The console output is:
10 20 30 11 22 33
70 80 90 77 88 99
70 80 90 77 88 99
10 20 30 11 22 33
Press any key to continue . . .
Here, the handicap is, you have to define as many pointers as number of constant member variables you have.

we can change the const variable value by the following code :
const int x=5;
printf("\nValue of x=%d",x);
*(int *)&x=7;
printf("\nNew value of x=%d",x);

#include<stdio.h>
#include<stdlib.h>
int main(void) {
const int a = 1; //a is constant
fprintf(stdout,"%d\n",a);//prints 1
int* a_ptr = &a;
*a_ptr = 4;//memory leak in c(value of a changed)
fprintf(stdout,"%d",a);//prints 4
return 0;
}

Final Solution: it will change const variable a value;
cont int a = 10;
*(int*)&a= 5; // now a prints 5
// works fine.

The step you're missing is that you don't need the int* pointer. The line:
const int *ptr_to_a = &a; // I still promiss i won't change a;
actually says you won't change ptr_to_a, not a. So if you changed your code to read like this:
const int a = 3; // I promise I won't change a
const int *ptr_to_a = &a; // I promise I won't change ptr_to_a, not a.
(*ptr_to_a) = 5; // a is now 5
a is now 5. You can change a through ptr_to_a without any warning.
EDIT:
The above is incorrect. It turns out I was confusing a similar trick with a shared_ptr, in which you can get access to the raw pointer and modify the internal data value without firing off any warnings. That is:
#include <iostream>
#include <boost/shared_ptr.hpp>
int main()
{
const boost::shared_ptr<int>* a = new boost::shared_ptr<int>(new int(3));
*(a->get()) = 5;
std::cout << "A is: " << *(a->get()) << std::endl;
return 0;
}
Will produce 5.

Related

How to get number of elements of string array via a pointer to a pointer

See Last line of code:
Trying to get number of elements from a array depending on a condition. How do i get the number of elements in an array when using an array like shown below:
using namespace std;
const char *options[3] = {"Option1", "Option2", "Option3"};
const char *options2[2] = {"Option1", "Option2"};
int main() {
const char **p;
if (true) {
p = options;
} else {
p = options2;
}
printf("%ld\n", sizeof(options)); // returns 24
printf("%ld\n", sizeof(options2)); // Returnns 16
printf("%ld\n", sizeof(options) / sizeof(p)); // returns 3
printf("%ld\n", sizeof(options2) / sizeof(p)); // returns 2
// How to use only pointer p to get the number of elements
printf("%ld\n", sizeof(p) / sizeof(p[0])); // returns 1 and not 3
return 0;
}
Sorry, but it is simply not possible to get an array's size from just a raw pointer to an array element.
One option is to store the array size in a separate variable alongside the array pointer, eg:
#include <iostream>
const char *options[3] = {"Option1", "Option2", "Option3"};
const char *options2[2] = {"Option1", "Option2"};
int main() {
const char **p;
size_t p_size;
if (some condition is true) {
p = options;
p_size = sizeof(options) / sizeof(options[0]); // or better: std::size(options) in C++17 and later
} else {
p = options2;
p_size = sizeof(options2) / sizeof(options2[0]); // or better: std::size(options2)
}
std::cout << sizeof(options) << "\n"; // returns 24
std::cout << sizeof(options2) << "\n"; // returns 16
std::cout << p_size << "\n"; // returns 3 or 2, based on condition
return 0;
}
In C++20 and later, you can use std::span instead (in C++14 and C++17, you can use gsl::span from the GSL library), eg:
#include <iostream>
#include <span>
const char *options[3] = {"Option1", "Option2", "Option3"};
const char *options2[2] = {"Option1", "Option2"};
int main() {
std::span<const char*> p;
if (some condition is true) {
p = options;
} else {
p = options2;
}
std::cout << sizeof(options) << "\n"; // returns 24
std::cout << sizeof(options2) << "\n"; // returns 16
std::cout << p.size() << "\n"; // returns 3 or 2, based on condition
return 0;
}
If you're going to write C++, write C++. You're starting from one of C's more questionable decisions, and then trying to force C++ to do the same thing. To twist Nike's phrase, "Just don't do it!"
std::array<char const *, 3> options {"Option1", "Option2", "Option3"};
std::array<char const *, 2> options2 {"Option1", "Option2"};
This makes it easy to retrieve the size of the array in question--and the size is part of the type, so all the work happens at compile time, so it imposes no runtime overhead. For example, if you do something like this:
template <class Array>
void showSize(Array const &a) {
std::cout << a.size() << "\n";
}
int main() {
showsize(options);
showSize(options2);
}
...what you'll find is that the compiler just generates code to write out the literal 3 or 2:
mov esi, 3 // or `mov esi, 2`, in the second case
call std::operator<<(std::ostream &, unsigned long)
[I've done a bit of editing to demangle the name there, but that's what the code works out to.]
Here's the un-edited version, in case you care.
If you really insist, you can side-step using an std::array as well:
const char *options[3] = {"Option1", "Option2", "Option3"};
const char *options2[2] = {"Option1", "Option2"};
template <class T, size_t N>
void showSize(T (&array)[N]) {
std::cout << N << '\n';
}
int main() {
showSize(options);
showSize(options2);
}
This doesn't actually use a pointer though--it passes the array by reference, which retains its type information, so the instantiated function template "just knows" the size of the array over which it was instantiated.
20 years ago, I'd have said this was a good way to do things. 10 years ago, I'd have preferred std::array, but realized it was new enough some compilers didn't include it yet. Nowadays, unless you really need to use an ancient (Pre-C++ 11) compiler, I'd use std::array.

A pointer to const int in c++

In c++ I have the next code
int main() {
int i = 1;
cout<<"i = "<<i<<endl; //prints "i = 1"
int *iPtr = &i;
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 1"
(*iPtr) = 12; //changing value through pointer
cout<<"i = "<<i<<endl; //prints "i = 12"
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 12"
system("pause");
return 0;
}
Now the same code with constant integer i
int main() {
const int i = 1;
cout<<"i = "<<i<<endl; //prints "i = 1"
int *iPtr = (int*)&i; //here I am usint a type conversion
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 1"
(*iPtr) = 12; //changing value through pointer
cout<<"i = "<<i<<endl; //prints "i = 1"
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 12"
system("pause");
return 0;
}
As you can see, in second case with constant integer, there are two different values for *iPtr and const i, but the pointer *iPtr shows to constant i.
Please tell me what happens in the second case and why?
Your second code has undefined behavior. You can't change const data via a pointer-to-non-const. You are lucky your code didn't simply crash outright when trying to modify a read-only value.
In any case, the result you are seeing is because the compiler knows that i is const and has a value that is known at compile time. So the compiler is able to optimize away i in the cout statement and use 1 directly instead. That is why you see 1 when printing i and see 12 when printing *iPtr.
You are trying to remove the const qualifier of your variable.
In C++, you should use const_cast to do that.
However, const_cast can only be used in some precise circomstances: constness should only be removed from pointers/references to data which have been declared non-const at top level, otherwise the compiler may optimize the variable and modifying it through the pointer/reference would result in undefined behaviour.
For example, this is not legal :
const int i = 1;
const int *iPtr = &i;
int *iSuperPtr = const_cast<int*>(iPtr);
*iSuperPtr = 2; // Invalid : i is first declared const !!
But this is totally legal :
void modifyConstIntPtr(const int *iPtr) {
int *iSuperPtr = const_cast<int*>(iPtr);
*iSuperPtr = 2; // Valid : i is first declared non-const !!
}
void modifyConstIntRef(const int &iRef) {
int &iSuperRef = const_cast<int&>(iRef);
iSuperRef = 3; // Valid : i is first declared non-const !!
}
int main() {
int i = 1;
modifyConstIntPtr(&i);
std::cout << i << std::endl;
modifyConstIntRef(i);
std::cout << i << std::endl;
}
This aspect of C++ is well detailed here: https://stackoverflow.com/a/357607/3412316)

Size of an object without using sizeof in C++

This was an interview question:
Say there is a class having only an int member. You do not know how many bytes the int will occupy. And you cannot view the class implementation (say it's an API). But you can create an object of it. How would you find the size needed for int without using sizeof.
He wouldn't accept using bitset, either.
Can you please suggest the most efficient way to find this out?
The following program demonstrates a valid technique to compute the size of an object.
#include <iostream>
struct Foo
{
int f;
};
int main()
{
// Create an object of the class.
Foo foo;
// Create a pointer to it.
Foo* p1 = &foo;
// Create another pointer, offset by 1 object from p1
// It is legal to compute (p1+1) but it is not legal
// to dereference (p1+1)
Foo* p2 = p1+1;
// Cast both pointers to char*.
char* cp1 = reinterpret_cast<char*>(p1);
char* cp2 = reinterpret_cast<char*>(p2);
// Compute the size of the object.
size_t size = (cp2-cp1);
std::cout << "Size of Foo: " << size << std::endl;
}
Using pointer algebra:
#include <iostream>
class A
{
int a;
};
int main() {
A a1;
A * n1 = &a1;
A * n2 = n1+1;
std::cout << int((char *)n2 - (char *)n1) << std::endl;
return 0;
}
Yet another alternative without using pointers. You can use it if in the next interview they also forbid pointers. Your comment "The interviewer was leading me to think on lines of overflow and underflow" might also be pointing at this method or similar.
#include <iostream>
int main() {
unsigned int x = 0, numOfBits = 0;
for(x--; x; x /= 2) numOfBits++;
std::cout << "number of bits in an int is: " << numOfBits;
return 0;
}
It gets the maximum value of an unsigned int (decrementing zero in unsigned mode) then subsequently divides by 2 until it reaches zero. To get the number of bytes, divide by CHAR_BIT.
Pointer arithmetic can be used without actually creating any objects:
class c {
int member;
};
c *ptr = 0;
++ptr;
int size = reinterpret_cast<int>(ptr);
Alternatively:
int size = reinterpret_cast<int>( static_cast<c*>(0) + 1 );

Confusion about pointer to an array as a function parameter

In my textbook about c++ I have the following code example:
using std::cout;
using std::endl;
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
cout << "Append: " << endl;
printArray(aArr, 4); cout << " + "; printArray(bArr, 3);
int* cArr = append(&aArr, bArr);
cout << " = "; printArray(cArr, 7); cout << endl;
return 0;
}
Does the "&" symbol in front of "aArr" in the call to append in main mean that the address of aArr is passed, or that a reference to aArr is passed.
The question then asks for me to implement a function append which takes two arrays: the first array (in the first argument) of size 4 by array pointer and the second array (in the second argument) of size 3 by reference and returns a pointer to an array of size 7. I have declared that function as (in the appropriate header file)
int* append( int foo[4], int (&secondArray) [3] );
Has the author perhaps misplaced the order of the "&" symbol in the append method (that it should be in front of "bArr")?
The compiler can help you out in cases like this.
Lets assume that this is the function prototype for your append function:
int* append( int foo[4], int (&secondArray) [3]);
I can test this out with this simple bit of code:
int* append( int foo[4], int (&secondArray) [3])
{
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
int* cArr = append(&aArr, bArr);
return 0;
}
But the compiler doesn't like this, failing with this error:
test.cpp(9): error C2664: 'int *append(int [],int (&)[3])':
cannot convert argument 1 from 'int (*)[4]' to 'int []'
As you can see it doesn't like the &aArr argument 1 at line 9 as it does not match the argument 1 defined by the function at line 1. From the error message it is even nice enough to give a reason why it thinks they don't line up.
Now using the hint from the compiler it is clear the function should in fact look like this:
int *append(int (*foo)[4], int secondArray[3])
{
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
int* cArr = append(&aArr, bArr);
return 0;
}
With that change the compiler is happy to accept the code as correct.
Now comparing the two you can see the difference is in the first case the first argument was passed as an array of 4 integers, whereas in the second case it is passed as the address of an array of four integers.
Just from the english you can tell these are two very different things.
EDIT: Here is an extension of that example that shows how to access the data inside the function.
#include <stdio.h>
int *append(int (*foo)[4], int secondArray[3] )
{
int *foo1 = *foo;
for (int i = 0; i < 4; ++i)
{
printf("foo: %d\n", foo1[i]);
}
for (int j = 0; j < 3; ++j)
{
printf("secondArray: %d\n", secondArray[j]);
}
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 12,13,11 };
int* cArr = append(&aArr, bArr);
return 0;
}
Compiling an running this code produces this output:
foo: 3
foo: 4
foo: 2
foo: 3
secondArray: 12
secondArray: 13
secondArray: 11

Why can't I change address of a pointer of type `const int *` when passed as function argument?

As far as I know, const int * implies that I can change the pointer but not the data, int * const says that I can't change the pointer address but I can change the data, and const int * const states that I can't change any of them.
However, I can't change a address of a pointer defined with the type const int *. Here is my example code:
void Func(const int * pInt)
{
static int Int = 0;
pInt = &Int;
Int++;
}
int wmain(int argc, wchar_t *argv[])
{
int Dummy = 0;
const int * pInt = &Dummy;
//const int * pInt = nullptr; // Gives error when I try to pass it to Func().
std::cout << pInt << '\t' << *pInt << std::endl;
std::cout << "-------------------" << std::endl;
for (int i=0; i<5; i++)
{
Func(pInt); // Set the pointer to the internal variable. (But, it doesn't set it!)
std::cout << pInt << '\t' << *pInt << std::endl;
}
return 0;
}
Code output:
00D2F9C4 0
-------------------
00D2F9C4 0
00D2F9C4 0
00D2F9C4 0
00D2F9C4 0
00D2F9C4 0
I would expect the address of pInt to change to point to the internal variable inside the Func() function after calling Func() for at least once. But it doesn't. I keeps pointing at the Dummy variable.
What is happening here? Why don't I get the result I expect?
(IDE: Visual Studio 2015 Community Version)
You don't see the change at the call site because you are passing the pointer by value. Modifying it inside Func will just change the local copy, not the pointer passed in.
If you want to modify the pointer and have the changes visible outside, pass it by reference:
void Func(const int *& pInt)
// ^