Ok, I know that this is invalid
char char_A = 'A';
const char * myPtr = &char_A;
*myPtr = 'J'; // error - can't change value of *myP
[Because we declared a pointer to a constant character]
Why is this valid?
const char *linuxDistro[6]={ "Debian", "Ubuntu", "OpenSuse", "Fedora", "Linux Mint", "Mandriva"};
for ( int i=0; i < 6; i++)
cout << *(linuxDistro+i)<< endl;
*linuxDistro="WhyCanIchangeThis";// should result in an error but doesnt ?
for ( int i=0; i < 6; i++)
cout << *(linuxDistro+i)<< endl;
Thanks for looking!
You write
*linuxDistro = "WhyCanIchangeThis";
which is perfectly valid, because the declaration of linuxDistro was
const char *linuxDistro[6];
i. e. it's an array of 6 pointers to const char. That is, you can change the pointers themselves, just not the characters pointed to by those pointers. I. e., you can not compile
*linuxDistro[0] = 'B';
to obtain the string "Bebian", becuse the strings contain constant characters...
What you probably want is an array of constant pointers to constant characters:
const char *const linuxDistro[6];
*linuxDistro is still a pointer, it is linuxDistro[0], *linuxDistro="WhyCanIchangeThis" it just change the pointer to point to a new address, not to modify the content in the old address, so it is OK.
If you write **linuxDistro='a', it should error.
because the pointer is a variable that stores a memory address, if a pointer is const the pointer keeps storing the same memory address, so the value of the pointer itself can't change, but you are saying nothing about the value pointed by the pointer, according to what you have, chaging the pointed value it's an allowed operation.
because char is not char[], so when you access to * of char[] you access the first element of it (Debian).
when you shift pointer (e.g. +1 it) you access next element of array
here is good example for better understanding
#include <iostream>
using namespace std;
int main ()
{
int numbers[5];
int * p;
p = numbers; *p = 10;
p++; *p = 20;
p = &numbers[2]; *p = 30;
p = numbers + 3; *p = 40;
p = numbers; *(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
return 0;
}
this will output:
10, 20, 30, 40, 50,
Related
I have
int some_var = 5;
int* ref_on_var = &a;
char arr[8];
char* to_write = reinterpret_cast<char*>(&ref_on_var);
I want to write ref_on_var to arr so i write this
for(size_t i = 0; i < sizeof(int*); ++i)
{
arr[i] = to_write[i];
}
This writes some bytes to array but when I try to get pointer back by
int* get = reinterpret_cast<int*>(arr);
I get incorrect address.
So what do I do wrong?
arr
This evaluates to a pointer to arr, that's the result of using the name of an array in a C++ expression.
This char buffer contains an int *, therefore this must be an int **. So:
int* get = *reinterpret_cast<int**>(arr);
#include <iostream>
using namespace std;
const int MAX = 4;
int main () {
const char *names[MAX] = { "Zara Ali", "Hina Ali", "Nuha Ali", "Sara Ali" };
for (int i = 0; i < MAX; i++) {
cout << "Value of names[" << i << "] = ";
cout << (names + i) << endl;
}
return 0;
}
what is (names + i) printing in the above code
what is char *names
names is an array of const char * pointers, which are being initialized to point at string literals in memory (which is irrelevant to the code being shown).
When an array is referred to by its name alone, it decays into a pointer to the first element. The loop is then using pointer arithmetic to increment that pointer to access each subsequent element. Thus, the expression names + i is effectively the same as &names[i], and so the loop is printing out the memory address of each element in the array, eg:
Value of names[0] = 0x7ffedc2f1850
Value of names[1] = 0x7ffedc2f1858
Value of names[2] = 0x7ffedc2f1860
Value of names[3] = 0x7ffedc2f1868
Online Demo
Had the code used *(names + i) instead, then it would be dereferencing those addresses, thus printing out each const char* pointer in the array. operator<< is overloaded to handle const char* as a null-terminated string, thus the contents of the string literals would be printed instead of their addresses, eg:
Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali
Online Demo
I have created 2 dynamic arrays in the main function. I have passed both of them to the function by reference. Then I copy data from smaller dynamic array to the larger dynamic array. I delete the smaller dynamic array. Assign the address of the larger dynamic array to the smaller dynamic array. Now ideally the arr array should have size of 10. However, when I try to print the 6th element of the array in the main, it crashes. Please have a look at the code below:
#include <iostream>
#include <string>
using namespace std;
void func(string * arr, string * brr);
int main()
{
string* arr = new string[5];
arr[0] = "hello0";
arr[1] = "hello1";
arr[2] = "hello2";
arr[3] = "hello3";
arr[4] = "hello4";
string* brr = new string[10];
func(arr, brr);
for(int i = 0; i < 6; i++)
cout << arr[i] << endl;
return 0;
}
void func(string * arr, string * brr)
{
for(int i = 0; i < 5; i++)
brr[i] = arr[i];
for(i = 0; i < 5; i++)
cout << brr[i] << endl;
delete []arr;
arr = brr;
arr[5] = "hello5";
}
This line has absolutely no effect for the caller:
arr = brr;
So after the call, arr points exactly where it used to point before - to a now invalid memory area (because you deleted it).
If this would be a C question, I would advise you to use a pointer to a pointer (string **arr). However, I feel this is nasty in a C++ program. Maybe you want to use a reference somewhere ?
Set this signature for the function
void func(string * & arr, string * & brr)
#cnicutar correctly diagnosed the problem; you'll either need to pass arr by reference (reference to the POINTER, not the array), of have fund return the new value of arr, which the caller can assign.
Given a pointer to int, how can I obtain the actual int?
I don't know if this is possible or not, but can someone please advise me?
Use the * on pointers to get the variable pointed (dereferencing).
int val = 42;
int* pVal = &val;
int k = *pVal; // k == 42
If your pointer points to an array, then dereferencing will give you the first element of the array.
If you want the "value" of the pointer, that is the actual memory address the pointer contains, then cast it (but it's generally not a good idea) :
int pValValue = reinterpret_cast<int>( pVal );
If you need to get the value pointed-to by the pointer, then that's not conversion. You simply dereference the pointer and pull out the data:
int* p = get_int_ptr();
int val = *p;
But if you really need to convert the pointer to an int, then you need to cast. If you think this is what you want, think again. It's probably not. If you wrote code that requires this construct, then you need to think about a redesign, because this is patently unsafe. Nevertheless:
int* p = get_int_ptr();
int val = reinterpret_cast<int>(p);
I'm not 100% sure if I understand what you want:
int a=5; // a holds 5
int* ptr_a = &a; // pointing to variable a (that is holding 5)
int b = *ptr_a; // means: declare an int b and set b's
// value to the value that is held by the cell ptr_a points to
int ptr_v = (int)ptr_a; // means: take the contents of ptr_a (i.e. an adress) and
// interpret it as an integer
Hope this helps.
use the dereference operator * e.g
void do_something(int *j) {
int k = *j; //assign the value j is pointing to , to k
...
}
You should differentiate strictly what you want: cast or dereference?
int x = 5;
int* p = &x; // pointer points to a location.
int a = *p; // dereference, a == 5
int b = (int)p; //cast, b == ...some big number, which is the memory location where x is stored.
You can still assign int directly to a pointer, just don't dereference it unless you really know what you're doing.
int* p = (int*) 5;
int a = *p; // crash/segfault, you are not authorized to read that mem location.
int b = (int)p; // now b==5
You can do without the explicit casts (int), (int*), but you will most likely get compiler warnings.
Use * to dereference the pointer:
int* pointer = ...//initialize the pointer with a valid address
int value = *pointer; //either read the value at that address
*pointer = value;//or write the new value
int Array[10];
int *ptr6 = &Array[6];
int *ptr0 = &Array[0];
uintptr_t int_adress_6 = reinterpret_cast<uintptr_t> (ptr6);
uintptr_t int_adress_0 = reinterpret_cast<uintptr_t> (ptr0);
cout << "difference of casted addrs = " << int_adress_6 - int_adress_0 << endl; //24 bits
cout << "difference in integer = " << ptr6 - ptr0 << endl; //6
I have a 3x3 array that I'm trying to create a pointer to and I keep getting this array, what gives?
How do I have to define the pointer? I've tried every combination of [] and *.
Is it possible to do this?
int tempSec[3][3];
int* pTemp = tempSec;
You can do int *pTemp = &tempSec[0][0];
If you want to treat a 3x3 array as an int*, you should probably declare it as an int[9], and use tempSec[3*x+y] instead of tempSec[x][y].
Alternatively, perhaps what you wanted was int (*pTemp)[3] = tempSec? That would then be a pointer to the first element of tempSec, that first element itself being an array.
You can in fact take a pointer to a 2D array:
int (*pTemp)[3][3] = &tempSex;
You'd then use it like this:
(*pTemp)[1][2] = 12;
That's almost certainly not what you want, but in your comment you did ask for it...
Its easyier to use a typedef
typedef int ThreeArray[3];
typedef int ThreeByThree[3][3];
int main(int argc, char* argv[])
{
int data[3][3];
ThreeArray* dPoint = data;
dPoint[0][2] = 5;
dPoint[2][1] = 6;
// Doing it without the typedef makes the syntax very hard to read.
//
int(*xxPointer)[3] = data;
xxPointer[0][1] = 7;
// Building a pointer to a three by Three array directly.
//
ThreeByThree* p1 = &data;
(*p1)[1][2] = 10;
// Building a pointer to a three by Three array directly (without typedef)
//
int(*p2)[3][3] = &data;
(*p2)[1][2] = 11;
// Building a reference to a 3 by 3 array.
//
ThreeByThree& ref1 = data;
ref1[0][0] = 8;
// Building a reference to a 3 by 3 array (Without the typedef)
//
int(&ref2)[3][3] = data;
ref2[1][1] = 9;
return 0;
}
Oh. That's easy!
int aai[3][3];
int* pi = reinterpret_cast<int*>(aai);
You can actually use this awesome technique to cast it into other wonderful types. For example:
int aai[3][3];
int (__stdcall *pfi_lds)(long, double, char*) = reinterpret_cast<int (__stdcall *)(long, double, char*)>(aai);
Isn't that just swell? The question is whether it's meaningful.
You're asking how to lie to your compiler. So the first thing to know is: Why do you want to lie?
int a[20][30];
int* b=&a[0][0];
As Steve pointed out, the proper form is int *pTemp = &tempSec[0][0];. int** pTemp2 = tempSec; does not work. The error given is:
cannot convert 'int (*)[3]' to 'int**' in initialization
It's not stored as an array of pointers to arrays. It's stored as one big vector, and the compiler hides the [a][b] = [a*rowLength+b] from you.
#include <iostream>
using namespace std;
int main()
{
// Allocate on stack and initialize.
int tempSec[3][3];
int n = 0;
for(int x = 0; x < 3; ++x)
for(int y = 0; y < 3; ++y)
tempSec[x][y] = n++;
// Print some addresses.
cout << "Array base: " << size_t(tempSec) << endl;
for(int x = 0; x < 3; ++x)
cout << "Row " << x << " base: " << size_t(tempSec[x]) << endl;
// Print contents.
cout << "As a 1-D vector:" << endl;
int *pTemp = &tempSec[0][0];
for(int k = 0; k < 9; ++k)
cout << "pTemp[" << k << "] = " << pTemp[k] << endl;
return 0;
}
Output:
Array base: 140734799802384
Row 0 base: 140734799802384
Row 1 base: 140734799802396
Row 2 base: 140734799802408
As a 1-D vector:
pTemp[0] = 0
pTemp[1] = 1
pTemp[2] = 2
pTemp[3] = 3
pTemp[4] = 4
pTemp[5] = 5
pTemp[6] = 6
pTemp[7] = 7
pTemp[8] = 8
Note that the Row 0 address is the same as the full array address, and consecutive rows are offset by sizeof(int) * 3 = 12.
Another way to go about doing this, is to first create an array of pointers:
int* pa[3] = { temp[0], temp[1], temp[2] };
Then create a pointer pointer to point to that:
int** pp = pa;
You can then use normal array syntax on that pointer pointer to get the element you're looking for:
int x = pp[1][0]; // gets the first element of the second array
Also, if the only reason you're trying to convert it to a pointer is so you can pass it to a function, you can do this:
void f(int v[3][3]);
As long as the size of the arrays are fixed, you can pass a two-dimensional array to a function like this. It's much more specific than passing a pointer.
Original post follows - please disregard, it is misinformed. Leaving it for posterity's sake ;)
However, here is a link I found regarding memory allocation of 2-dimensional arrays in c++. Perhaps it may be of more value.
Not sure it's what you want, and it's been a while since I've written c++, but the reason your cast fails is because you are going from an array of arrays to a pointer of ints. If, on the other hand, you tried from array to array to a pointer of pointers, it would likely work
int tempSec[3][3];
int** pTemp = tempSec;
remember, your array of arrays is really a contiguous block of memory holding pointers to other contiguous blocks of memory - which is why casting an array of arrays to an array of ints will get you an array of what looks like garbage [that garbage is really memory addresses!].
Again, depends on what you want. If you want it in pointer format, pointer of pointers is the way to go. If you want all 9 elements as one contiguous array, you will have to perform a linearization of your double array.
Let's ask cdecl.org to translate your declaration for us:
int tempSec[3][3]
returns
declare tempSec as array 3 of array 3 of int
Ok, so how do we create a pointer to that? Let's ask cdecl again:
declare pTemp as pointer to array 3 of array 3 of int
returns
int (*pTemp)[3][3]
Since we already have the array 3 of array 3 of int, we can just do:
int (*pTemp)[3][3] = &tempSec;
int tempSec[3][3];
int* pTemp = tempSec[0];