Pointers of two dimensional array - c++

There is such code:
int (*ptr_)[1] = new int[1][1];
ptr_[0][0] = 100;
std::cout << "to: " << &ptr_ << ' ' << ptr_ << ' ' << *ptr_ << ' ' << &(*ptr_) << ' ' << **ptr_ << std::endl;
Result is:
to: 0xbfda6db4 0x9ee9028 0x9ee9028 0x9ee9028 100
Why values of ptr_ and *ptr_ are the same? Value of ptr_ equals to 0x9ee9028, so value of memory cell 0x9ee9028 is *ptr_ which is 0x9ee9028, however **ptr_ gives result 100. Is it logical?

ptr_ is a pointer to an array of length one. Variables of array type in C and C++ simply degrade to pointers when printed (among other things). So when you print ptr_ you get the address of the array. When you print *ptr_ you get the array itself, which then degrades right back into that same pointer again.
But in C++ please use smart pointers and standard containers.

int main() {
int test[2][3] = { {1,2,3}, {4, 5, 6} };
int (*pnt)[3] = test; //*pnt has type int[3]
//printArray writes array to stdout
printArray(3, *pnt); //returns 1 2 3
printArray(3, *(pnt+1)); //returns 4 5 6
return 0;
}
mutl-dimentional arrays are really arrays for arrays, for example test[2][3] is an array with two elements that are of type int[3] which in turn have 3 integer elements.
In your case you have a pointer to a pointer to a variable.
In other words your array looks like this:
array = {{100}}
ptr_ points to array
&ptr_ is the address of outer array
ptr_ is the address of first element (which is to another array)
*ptr_ same as above
&(*ptr_) gets first element of outer array which is the innter array, then returns the address of the innter array
**ptr_ gets first element of outer array (which is the inner array) then dereferences the innter array which is an actuall value

Related

Does multi dimension array matter when passing it to a function?

So i have a function and a MD array
int arrayMD[2][2] = { 0,3,6,8 };
void display(int *ptr) {
cout << *(ptr + 1);
}
display(*arrayMD, 2, 2); // Invoke
When I pass the it to the function it will point to a 1-D Array
so the *ptr would point to {0,3} (CMIIW)
When I call a function / invoke
I pass a dereferenced pointer which is : An Address
cout << *arrayMD == Address to the first one which is {0,3}
so the function should be *ptr = Address from dereferenced Argument passed
So when i try to double bracket on the array: ptr[0][1] it doesn't work because it has become 1 dimensional array which consist of {0,3} but when i type ptr[3] it printed out 8. I know how it stored in the memory but is there no limit? so i could just use one dimensional array and print out the value. Then what's the point of 2D array?
I have just started learning C++ so please CMIIW
Let's put it this way first:
void display(int (*ptr)[2]) { // Takes a pointer to an array of 2 ints
std::cout << **(ptr); // Display [0][0]
std::cout << *(*(ptr)+1); // Display [0][1]
std::cout << **(ptr+1); // Display [1][0]
std::cout << *(*(ptr+1)+1); // Display [1][1]
}
int main() {
int arrayMD[2][2] = { 0,3,6,8 };
display(arrayMD); // Here, we pass the pointer to the first element of arrayMD
}
This gives us the following output:
0368
As you know, when we use the name of an array, it is automatically converts to the pointer to the first element. But when we want a pointer to an array, we need involvement of parenthesis:
int *p[100]; // is an array of 100 pointers to int
int (*p)[100]; // is a pointer to an array of 100 int
And yes, in general, consider using Standard Library, in particular the std::array.

Understanding C++ syntax for array pointers double brackets

I writing a script which receives a structure (Evt) which holds an array of pointers uint16_t *DataChannel[Evt->ChSize[ch]]. I can then loop over the data and print out of the value as so:
for(uint16_t ch=0; ch<sizeof(Evt->DataChannel)/sizeof(Evt->DataChannel[0]); ++ch){
for(int adc_it=0; adc_it<(Evt->ChSize[ch]); ++adc_it){ for(int adc_it=0; adc_it<(Evt->ChSize[ch]); ++adc_it){
std::cout << (Evt->DataChannel)[ch][adc_it] << " ";
}
}
I don't understand where the second bracket comes from ([adc_it]), what it is doing and how it works. I think (Evt->DataChannel) should be a uint16_t which is not an array so why the second bracket?
I tried to replicate this in a quick piece of code:
#include <iostream>
int main()
{
int* test[10];
*(test[0]) = 5;
std::cout << test[0][0] << std::endl; //Gives 5
std::cout << test[0][1] << std::endl; //Seg faults
return 0;
}
Again can some explain what test[0][0] is doing because I have no idea and why it runs but test[0][1] fails?
Cheers
Dom
C++ permits the use of array notation [ ] when dereferencing a pointer.
In the simplest case, you can say something like:
char *ptr = new char[10];
That creates a pointer to char, which points to the first character in an array of ten characters allocated with new[].
After doing this:
char ch = *ptr;
and
char ch = ptr[0];
do the exact same thing. However since there are 10 characters in the array, you can also say:
char ch5 = ptr[5];
to access an element further up the array.
This leads to an eqivalence in C++ (and C, where it originated) that:
ptr[x];
is identical to:
*(ptr + x);
for any pointer / array referenced by ptr and any index x.
Already the first part
int* test[10];
*(test[0]) = 5;
is undefined behaviour, because you dereference an uninitialized pointer value.
Explanation:
int* test[10] is an array of 10 pointers to ints, each pointer
being not initialized and definitely not pointing to a memory that
you reserved to store ints.
test[0] gives an uninitialized pointer; already this statement is
UB
*(test[0]) = 5 dereferences an arbitrary pointer value, definitely
UB
Try:
int* test[10];
int firstLine[5] = { 1,2,3,4,5 };
test[0] = firstLine;
cout << test[0][0]; // gives 1, firstLine[0]
cout << test[0][1]; // gives 2, is the same as firstLine[1]
// cout << test[1][0]; // undefined behaviour, the second pointer in array test is not initialized

Are character arrays the only type that have some form of null-termination?

I've read some of my friend's code and seen functions like this:
int foo(int* arr, int n)
{
// ...
}
which he then calls like this:
int myArr [] = {69, 69, 69, 69, 69};
int f = foo(myArr, sizeof(myArr)/sizeof(int));
Now, I understand that sizeof(myArr)/sizeof(int) is dividing the size of myArr in bytes by the size of an int in bytes, thus returning the length of myArray. However, I don't understand how sizeof(myArr) is implemented unless there's some sort of generic null element that terminates arrays and then sizeof(...) works similar to how strlen(...) works:
size_t strlen(char* c)
{
size_t k = 0;
while (*c != '\0')
{
++k;
++c;
}
return k;
}
Now, if sizeof(...) does work similar to that, then I don't see why, when passing an array to a function, you can't simply do
int foo(int* arr)
{
int n = sizeof(arr)/sizeof(int);
// ....
}
which is simpler way of writing functions because the array is essentially being passed in as a single unit that gets unpacked.
My guess is that arrays of non-character type don't have the null-termination property that character arrays do. In that case, how does sizeof(...) work? And what is the point of null-termination in character arrays anyhow? Why are they created differently than any other array?
Anyways, I was wondering whether someone could clear up all the obvious confusion that I have.
sizeof works on arrays because the compiler knows the length at compile time. If you pass that array to a function, it turns into a pointer, at which point the compiler doesn't know the full size of the array anymore.
For example:
#include <iostream>
void printPointerSize(int* a) {
// a is a pointer, and all pointers are 8 bytes (64 bits) on my machine
std::cout << "int* pointer argument has size: " << sizeof a << std::endl;
}
int main() {
// the compiler determines from the initializer that this is an int[5]
int a[] = {1, 2, 3, 4, 5};
// since the compiler knows that a is an int[5],
// then sizeof a is 5 * sizeof int
std::cout << "int[5] has size: " << sizeof a << std::endl;
printPointerSize(a);
}
Output (on a platform with 64-bit pointers and 32-bit integers):
int[5] has size: 20
int* pointer argument has size: 8
Note that if you try to create a function that takes an array as an argument, the compiler will just turn it into a pointer anyway:
void printPointerSize(int a[5]) {
// this will print the size of a pointer,
// not the size of a 5-element int array
std::cout << "int[5] argument has size: " << sizeof a << std::endl;
}
In addition to Brandon's answer, you need to distinguish between array capacity and array size.
Array Capacity
Array Capacity is the maximum number items the array can hold. There can be from 0 to capacity number of items in the array. Which brings up the question, "how many items are in the array?"
Array Size
Array Size is the number of valid items in the array. An array that has a capacity of 20 items, may only have 3 valid items in it.
Example:
char array[20];
array[0] = 'M';
array[1] = 'e';
array[2] = 'a';
array[3] = 't';
The above array has a capacity of 20, but only 4 valid items.
Repeating the question, "How many items are in the array?"
The C++ language does not maintain the number of items in an array. The sizeof operator returns the capacity of an array, but not the size.
The size of an array must be maintained in a separate variable. Some crafty programmers can use an array slot to maintain this value. So when passing an array, you will have to pass: the array (or pointer to it), the capacity and the size. Most starting programmers forget about the size parameter, which leads to many difficult defects that are hard to find.

Having difficulty working with pointers

I having some issue when it comes to initializing pointers.
void findMM (int *PMM, int *theG)
{
// code I haven't written yet. It will essentially take two variables from //theG and store it in MM
}
int main()
{
int size;
int MM [2] = {1000, 0};
int *theG = NULL;
cout << "\nPlease insert size of array:" << endl;
cin >> size;
theG = new int [size];
findMM(&MM, &theG); //Get error with &MM
delete [] theG;
return 0;
}
The complier says that argument of type int (*)[2] is incompatible with parameter of type int ** So obviously that I have issue with the code in particular my (reference?) of array MM. Or perhaps there is other obvious faults that I am missing?
Edit attempt 2
void findMM (int *PMM, int *theG)
{
PMM [1] = 5;
theG [0] = 7;
}
int main()
{
int size;
int MM [2] = {1000, 0};
int *theG = NULL;
cout << "\nPlease insert size of array:" << endl;
cin >> size;
theG = new int [size];
findMM(MM, theG);
cout << MM [1] << endl << theG[0];
delete [] theG;
return 0;
}
The output would be 5 and 7 correct?
Since MM is an array, &MM is a pointer to an array (that's the type int (*)[2] that you see in the error). Instead, you seem to want to pass a pointer to the first element of the array. There are two ways to do that. Firstly, you can explicitly get the first element and then take the address of it: &MM[0]. Secondly, you can rely on array-to-pointer conversion to do it for you and just pass MM. Array-to-pointer conversion converts an array to a pointer to its first element.
I know this question has already been answered but I believe I can contribute to the asker's understanding.
Let's start with the basics:
void main()
{
int a = 2; // a is an int
cout << a << endl; // print 2
int *b; // b is a pointer-to-int
b = &a; // store the address of a in b
cout << *b << endl;// print the value that b points to, which is 2
int my_array = new int[3]; // allocate an array with 3 integers
my_array[0] = 50; // store 50 in the first element of the array
my_array[1] = 51; // store 51 in the second element of the array
my_array[2] = 52; // store 52 in the third element of the array
cout << c[0] << endl; // print 50
some_function(my_array, 3); // explained below
}
Now let's see how to pass arrays into functions. Assume we want to have a function called some_function that receives an array.
void some_function(int *some_array, int size_of_the_array)
{
// use the array however you like here
}
The function some_function receives a pointer to an int (also known as "pointer-to-int"). The name of an array is always the address of its first element, so if a function expects a pointer to an int and you give it the name of an array of ints, you are actually giving it the address of the first element in the array (this is just C++ syntax rules). So the function now has the address of the first element in the array, it can do stuff like *some_array to access the first element in the array, but what if it wants to access the other elements? It adds 1 to the pointer it already has and then applies the * operator to it: *(some_array + 1). Let's say an int is 4 bytes, if you add 1 to a pointer-to-int, the result of this addition is a new pointer that points to a location in memory 4 bytes ahead, so *(some_array + 93) is the value in the 94th element of the array some_array (array elements are stored sequentially in memory). A shorthand notation for this is some_array[93]. So if you have int *some_array = new int[100];, then some_array is a pointer and some_array[93] is the same as *(some_array + 93), which is the 94th element in the array.
The address itself though is not enough, you also need to know the number of entries in the array so that you don't try to access an element past the end of the array. In this example, assume that some_function simply prints the contents of the array, so if you don't provide 3 as the second argument to the function then it will have no way of knowing when to stop adding 1 to the pointer it received in the first argument. Beware, however, that by passing an array to a function this way, you are not passing the function a copy of the array, you are simply telling it where to find its contents in memory.

C++: array for loop printing addresses instead of values

this was an example given to us in class. Could someone explain to me why this prints 29 addresses instead of 29 "0" (zeroes) ?
int num[29]; is an array which has set aside 29 addresses for 29 integers -i get that part, but in the for loop you arent u printing the values IN those addreses rather than the addresses themselves?
also, whats the difference between (num+i) and (num[]+i)?
I'm a little confused..
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int num[29];
for (int i=0;i<29;i++)
cout << (num+i) << endl;
return 0;
}
The reason for printing addresses is that
(num+i)
Is the address of the ith element of the array, not the ith element itself. If you want to get the ith element, you can write
*(num + i)
Or, even better:
num[i]
As for your second question - the syntax (num + i) means "the address i objects past the start of num, and the syntax (num[] + i) is not legal C or C++.
Hope this helps!
A declaration such as:
int num[29];
defines a contiguous array of 29 integers.
To access elements of the array use num[i] where i is the index (starting at 0 for the 1st element).
The expression num on its own gives a pointer (memory address and type) of the first element of the array.
The expression ptr + i (where ptr is a pointer and i is an integer) evaluates to a pointer that is i positions (in units of the type of pointer) after ptr.
So num + i gives a pointer to the element with index i.
The expression &a gives a pointer to some object a.
The expression *ptr gives the object that some pointer ptr is pointing at.
So the expressions a and *(&a) are equivalent.
So num[5] is the same as *(num+5)
and num+5 is the same as &num[5]
and num is the same as &num[0]
When you print a pointer with cout it will show its address.
When you print an object it will print the value of the object.
So
cout << num + 5;
will print the address of the 5th (zero-indexed) element of num
and
cout << num[5];
will print the value of the 5th (zero-indexed) element of num