Understanding 2D array with dynamic memory allocation - c++

Can someone please help me understand the last line in this snippet of code? I don't understand how that dynamically allocates the 2D array. I understand that on line 6, it's creating a pointer named 'a' and pointing it to an array of integers of size 5 as defined by 'c'.
What I don't understand is how that "new int" statement works with the r thrown into the equation. Thanks in advance.
#include <iostream>
const int c = 5; //num of columns
int main () {
int r = 5;
int (*a)[c];
a = new int[r][c]; // allocate array
}

If you have a type T and are going to allocate an array of size N then this expression
new T[N]
returns the address of the type T * of the first element of the allocated array.
So you should write
T *a = new T[N];
For example if T is equivalent to the type int
typedef int T;
or
using T = int;
then the above allocation can be written
int *a = new int[N];
the size of element of the array is equal to sizeof( int ) and usually is 4 bytes.
Now let's assume that you are going to allocate an array of elements of type int[M] where M is a constant integer expression.
You can write
typedef int T[M];
or
using T = int[M];
and
T *a = new T[N];
So you allocated an array of N elements where each element has size sizeof( int[M] and the pointer a points to the first element of the array.
Because T is equivalent tp int [M] you can write
int ( *a )[M] = new int [N][M];
that is this statement allocates an array of N elements of the type int[M] and the pointer a gets the address of the first element of the allocated array.
Returning to your program example
int r = 5
int (*a)[c];
a = new int[r][c];
you can rewrite it the following way
typedef int T[c];
or
using T = int[c];
and
T *a = new T[r];
that is this statements allocates an array of r elements (objects) of type int[c] and a is pointer to the first element of the allocated array.

You're just making a pointer to a one-dimensional array, which requires two indexes to access elements. Nothing crazy, not quite undefined behavior, but not good either.
#include <iostream>
const int c = 5; //num of columns
int main () {
int r = 5;
//Creates a pointer to an array of 5 integer pointers.
int (*a)[c];
a = new int[r][c]; // allocate array
std::cout << *a << std::endl;
std::cout << a << std::endl;
std::cout << std::endl;
std::cout << "Displaying deferenced, unallocated array." << std::endl;
for(int i=0; i<c;++i){
std::cout << *a[i] << std::endl;
}
std::cout << "Diplaying pointers in the array." << std::endl;
std::cout << "Note how it's not a 2d array." << std::endl;
for(int i=0;i<c;++i){
for(int j=0;j<r;++j){
std::cout << a[i] << " ";
}
std::cout << std::endl;
}
std::cout << "Allocating array 1d, 1d style fails..." << std::endl;
/*
for(int i=0;i<c;++i){
a[i] = 23; //Syntax error! Requires two indexes.
}
*/
std::cout << "Allocating 1d array 2d style... success!?" << std::endl;
for(int i=0;i<r;++i){
for(int j=0;j<c;++j){
a[i][j] = 13;
}
}
std::cout << "Displaying allocated array." << std::endl;
for(int i=0;i<r;++i){
for(int j=0;j<c;++j){
std::cout << a[i][j] << " ";
}
std::cout << std::endl;
}
delete [] a;
}
Outputs:
0x100202ba0
0x100202ba0
Displaying deferenced, unallocated array.
0
0
0
0
0
Diplaying pointers in the array.
Note how it's not a 2d array.
0x100202ba0 0x100202ba0 0x100202ba0 0x100202ba0 0x100202ba0
0x100202bb4 0x100202bb4 0x100202bb4 0x100202bb4 0x100202bb4
0x100202bc8 0x100202bc8 0x100202bc8 0x100202bc8 0x100202bc8
0x100202bdc 0x100202bdc 0x100202bdc 0x100202bdc 0x100202bdc
0x100202bf0 0x100202bf0 0x100202bf0 0x100202bf0 0x100202bf0
Allocating array 1d, 1d style fails...
Allocating 1d array 2d style... success!?
Displaying allocated array.
13 13 13 13 13
13 13 13 13 13
13 13 13 13 13
13 13 13 13 13
13 13 13 13 13
Program ended with exit code: 0

Related

How can I calculate size of Array in C++

I had the online coding interview today and I really struggled while trying to calculate the size of the array.
Could you please help me with how can I measure the sizeof array here? I tried my best but no luck please help here.
#include<iostream>
#include<map>
#include<vector>
using namespace std;
void arraysize(int* a) {
cout << "size1: "<<sizeof(a) << endl;
cout << "size2: " << sizeof(a[0]) << endl;;
}
int main()
{
int array1[] = { 1,2,3,4,5,6,7,8 };
arraysize(array1);
return 0;
}
Result:
size1: 4
size2: 4
In most cases, when you pass an array to a function, the array will be converted to a pointer. This is called an array-to-pointer decay. Once this decay happens, you lose the size information of the array. That is, you can no longer tell the size of the original array from the pointer.
However, one case in which this conversion / decay will not happen is when we pass a reference to the array. We can take advantage of this property to get the size of an array.
#include<iostream>
template<typename T, size_t N>
size_t asize(T (&array)[N])
{
return N;
}
int main()
{
int array1[] = { 1,2,3,4,5,6,7,8 };
std::cout << asize(array1) << std::endl; // 8
return 0;
}
In the above case, to the template function asize, we pass a reference to an array of type T[N], whose size is N. In this case, it is array type int[8]. So the function returns N, which is size 8.
C style array's decay to pointer's when passed to a function like this.
The first cout statement is printing the size of a pointer on your machine.
The second cout statement is printing the size of an integer.
Use one of the following solutions in order to pass the size of the array to the function.
template<std::size_t N>
void ArraySize( int ( &array )[ N ] )
{
std::cout << "Array size: " << N << '\n';
}
void ArraySize( int* array, std::size_t size )
{
std::cout << "Array size: " << size << '\n';
}
template<std::size_t N>
void ArraySize( std::array<int, N>& array )
{
std::cout << "Array size: "<< array.size( ) << '\n';
}
sizeof(a) returns the number of bytes in array,
sizeof(int) returns the number of bytes in an int,
ergo
sizeof(a)/sizeof(int) returns the array length
Easiest way to get the size of an array:
#include <iostream>
using namespace std;
int main(void) {
int ch[5], size;
size = sizeof(ch) / sizeof(ch[0]);
cout << size;
return 0;
}
Output: 5
simply divide sizeof(array1) by sizeof(int). it will give you total element in array. because sizeof(array1) will give total bytes in the array. for example sizeof(array1) = int * 8 because your array is int so int is 4 byte answer is 4*8 = 32.Now you have to divide it again by 4 cause its in byte.
cout << "Size of the Array is : " << sizeof(array1)/sizeof(int) << endl;
put above code in your main function to get result

C++ Function Return Issue [duplicate]

This question already has answers here:
getting size of array from pointer c++
(6 answers)
Closed 3 years ago.
I am trying to make a function that can return the size of an array that can be different data types. I believe the expression (sizeof(z)/sizeof(*z))) returns the memory allocated to z divided by the memory size of the data type. The following code is my attempt to overload the function and return the size of the array as an integer. When I run the expression in the main function it works, but when I try to pass the array to the function I do not get the correct values and not sure what I am doing wrong. 68 / 4 = 17 which is the correct size of the array.
(1) outputs sizeof(z) and sizeof(*z) in the size function
(2) expression in main function
(3) outputs sizeof(z) in the main function
(4) outputs sizeof(*z) in the main function
#include <iostream>
using namespace std;
//
int size(int *data){
cout << sizeof(data) << ", " << sizeof(*data) << ", ";
return((sizeof(data))/(sizeof(*data)));
}
int size(char *x){return(sizeof(x)/sizeof(*x));}
int size(float *x){return(sizeof(x)/sizeof(*x));}
int size(double *x){return(sizeof(x)/sizeof(*x));}
int size(short int *x){return(sizeof(x)/sizeof(*x));}
int size(long int *x){return(sizeof(x)/sizeof(*x));}
int main(){
double x[9];
int z[17];
char k[29];
cout << "(1) Size : " << size(z) << endl;
cout << "(2) Size : " << (sizeof(z)/sizeof(*z)) << endl;
cout << "(3) Size : " << sizeof(z) << endl;
cout << "(4) Size : " << sizeof(*z) << endl;
cout << "(5) Size : " << size(z) << endl;
cout << "(6) Size : " << size(k) << endl;
return 0;
}
Terminal Output:
(1) Size : 8, 4, 2
(2) Size : 17
(3) Size : 68
(4) Size : 4
(5) Size : 8, 4, 2
(6) Size : 8
An array decays to a pointer when you pass it to another function, so sizeof(arr) will give you the actual amount of memory allocated, only in the scope of the function in which arr was declared.
There's a common mistake:
char* a // is a pointer
char b[] // is an array
when using:
char b[5]; // is an array of 5 bytes
sizeof(b); // 5
// but
char* a = b;
sizeof(a); // 8 (x64)
the last sizeof(a) is giving you the sizeof char * which is a pointer.
You can pass the name of an Array as a Pointer to the size() function, but in that function, the argument is treated as Pointer.

C++ Access Violation reading location 0xDDDDDDCD when I try to delete an array UPDATED

I'm working on a homework assignment. I'm trying to overload the "=" operator for an Array class I'm creating so that it will assign a newly created array with the same values as another array. This seems to work. The array is created and the data is copied over. I also check the location of the arrays first element and it is different than the original so I don't think it's trying to delete an array that's already deleted.
I've tried messing around with my destructor, but I honestly have no idea where this is coming from. If anyone has any debugging strategies that might help, I'd love to hear them as well.
Driver.cpp
int main ()
{
//Initialize
int size = 0;
char fill = '\0';
//Get info about the array
std::cout << "How long should the array be?" << std::endl;
std::cin >> size;
std::cout << "Choose fill character." << std::endl;
std::cin >> fill;
//Create array & Print array details
Array* arr = new Array(size, fill);
std::cout << "The array size is: " << arr->size() << std::endl;
std::cout << "max size: " << arr->max_size() << std::endl;
std::cout << "The contents of the array is: ";
arr->printArr();
std::cout << std::endl;
//Create new array & set it's values equal to old array
Array* arr2 = new Array();
arr2 = arr;
//= OVERLOAD TESTING
std::cout << "The array size is: " << arr2->size() << std::endl;
std::cout << "max size: " << arr2->max_size() << std::endl;
std::cout << "The contents of the array is: ";
arr2->printArr();
//Deallocate memory
delete arr;
arr = nullptr;
delete arr2;
arr2 = nullptr;
//Checking for memory leaks
_CrtDumpMemoryLeaks();
return 0;
}
Array.cpp file
//Define MAX SIZE so that it can be easily changed.
#define MAX_SIZE_ 200
#include "Array.h"
#include <iostream>
#include <stdexcept>
Array::Array (void)
:data_ (new char[MAX_SIZE_]),
cur_size_ (0),
max_size_ (MAX_SIZE_)
{ }
//Overloaded Constructor
//Assigns the initial size of the array and fills each element with the character stored in fill.
Array::Array (size_t length, char fill)
: data_ (new char[length]),
cur_size_ (length),
max_size_ (length)
{
//Fill each element with the character passed in to the function.
for(int i = 0; i < length; i++)
{
this-> data_[i] = fill;
}
std::cout << &this->data_ << std::endl;
}
//Destructor
Array::~Array (void)
{
delete[] this->data_;
this->data_ = nullptr;
}
//Sets new array equal to rhs.
const Array & Array::operator = (const Array & rhs)
{
//Set current and max size values to new array.
this->max_size_ = rhs.max_size_;
this->cur_size_ = rhs.cur_size_;
//Copy data from rhs.data_ to new array's data_
for(int i = 0; i < rhs.cur_size_; i++)
{
this->data_[i] = rhs.data_[i];
}
return *this;
}
//Print the contents of the array.
void Array::printArr(void)
{
for (int i = 0; i < (this->cur_size_) ; i++)
{
std::cout << this->data_[i];
}
}
Expected Results: The program displays information about the different arrays, then deletes them with no memory leaks.
Actual Results: The program displays all the correct data for both arrays and is able to delete the first array without a hitch, but runs into an exception when calling:
delete[] this->data_;
on the second array.
> Exception thrown at 0x5D13DB1B (ucrtbased.dll) in driver.exe: 0xC0000005: Access violation reading location 0xDDDDDDCD
Thanks for any help!
When you do arr2 = arr; you copy the pointer (memorty address) hold by arr into arr2:
Array* arr2 = new Array();
arr2 = arr;
So after that call, both arr2 and arr hold the same pointer (point to the same object). As of that delete arr2; will delete the same object you already deleted when you did delete arr; two lines before:
delete arr;
arr = nullptr;
delete arr2;
So doing delete arr2; here causes already undefine behavior. At that point, anything could happen.

What's a practical use-case for "address of array"?

(Disclaimer: Pointers in C++ is a VERY popular topic and so I'm compelled to believe that someone before me has already raised this point. However, I wasn't able to find another reference. Please correct me and feel free to close this thread if I'm wrong.)
I've come across lots of examples that distinguish between pointer to first element of array and pointer to the array itself. Here's one program and its output:
//pointers to arrays
#include <iostream>
using namespace std;
int main() {
int arr[10] = {};
int *p_start = arr;
int (*p_whole)[10] = &arr;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
cout << "Adding 1 to both . . . " <<endl;
p_start += 1;
p_whole += 1;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
return 0;
}
Output:
p_start is 0x7ffc5b5c5470
P_whole is 0x7ffc5b5c5470
Adding 1 to both . . .
p_start is 0x7ffc5b5c5474
P_whole is 0x7ffc5b5c5498
So, as expected, adding 1 to both gives different results. But I'm at a loss to see a practical use for something like p_whole. Once I have the address of the entire array-block, which can be obtained using arr as well, what can I do with such a pointer?
For single arrays, I don't think there's much point to it. Where it becomes useful is with multi-dimensional arrays, which are arrays of arrays. A pointer to one of the sub-arrays is a pointer to the row, and incrementing it gets you a pointer to the next row. In contrast, a pointer to the first element of the inner array is a pointer to a single element, and incrementing it gets you the next element.
int (*)[10] is a "stronger" type than int* as it keeps size of the array,
so you may pass it to function without passing additional size parameter:
void display(const int(*a)[10]) // const int (&a)[10] seems better here
{
for (int e : *a) {
std::cout << " " << e;
}
}
versus
void display(const int* a, std::size_t size) // or const int* end/last
{
for (std::size_t i = 0; i != size; ++i) {
std::cout << " " << a[i];
}
}

Point one array value to another value of the same array - C++

Imagine I have the following code:
int* firstArray[4];
fill_n(firstArray, 4, 0);
//firstArray values are: 0, 0, 0, 0
int* secondArray[4];
fill_n(secondArray, 4, 1);
//secondArray values are: 1, 1, 1, 1
Would there be a way to link the first value of firstArray to the first value of secondArray so that if I do:
secondArray[0] = 20;
//secondArray values would be: 20, 1, 1, 1 (because I just changed it)
//firstArray values would be: 20, 0, 0, 0 (because it's pointing to the value I just changed)
As far as I've tested and researched I can't do something along those lines.
P.S.: This is to create a Samurai Sudoku (in which some chunks of numbers are shared), so when I modify a value that 2 sudokus share it would be updated in both.
You are mixing up concepts. You don't even need to declare a second array just do this:
int myarray [20];
int * mypointer;
mypointer = myarray;
// then you can use both mypointer[] myarray[] the same way to access array elements
The concept of arrays is related to that of pointers. In fact, arrays work very much like pointers to their first elements, and, actually, an array can always be implicitly converted to the pointer of the proper type.
The [] operator in arrays acts the same way as a as a de-referencing operator, but with the added ability of automatically advancing the pointer according to the data type. This is why Array[1] references the same value as *(Array+1)
however you are declaring an arrays of pointers to integers, which means that you can't "store" integer values in this array, but rather store the value of the address where the integer is located.
Additionally when you declare an array you are essentially declaring a constant pointer, so you can not "steal" it and make it pointer to another location.
Study this Code and it's output (RUN THIS CODE)
#include <iostream>
using namespace std;
void printarray (int arg[], int length) {
for (int n=0; n<length; ++n)
cout << arg[n] << ' ';
cout << '\n';
}
int main ()
{
int first[] = {5, 10, 15, 14, 13};
printarray (first,3);
// int* third[] = {1,1,1}; Not accepted because int is not int*
// storing the addresses of first as pointers in 2 different arrays
int* third[] = {first,first+2,first+3};
int* forth[] = {first,first+2,first+3};
// the memory adress where the pointers TO first is stored
cout << third << endl;
cout << forth << endl;
cout << &third << endl;
cout << &forth << endl;
// the memory adress where the pointer TO the value of first[0] is stored
cout << *third << endl;
cout << *forth << endl;
cout << third[0] << endl;
cout << forth[0] << endl;
// you are defrencing twice
cout << *third[0] << endl;
cout << *forth[0] << endl;
cout << **third << endl;
cout << **forth << endl;
// assign once
first[0] = 77;
// applys to all values
cout << first[0] << endl;
cout << *third[0] << endl;
cout << *forth[0] << endl;
// better yet declare a int* and use it same way your array
int* second;
second = first;
cout << first[0] << endl;
cout << second[0] << endl;
// again change value and the change is reflected everywhere
second[0] = 99;
cout << first[0] << endl;
cout << second[0] << endl;
cout << *third[0] << endl;
cout << *forth[0] << endl;
}
OUTPUT
5 10 15
0x786378c0b860
0x786378c0b880
0x786378c0b860
0x786378c0b880
0x786378c0b840
0x786378c0b840
0x786378c0b840
0x786378c0b840
5
5
5
5
77
77
77
77
77
99
99
99
99
Store int**s instead of int*s this way you can have each entry in the array point to the same address.
You would initialize the first element lets say as:
int *first = new int;
*first = 1;
firstArray[0] = first;
secondArray[0] = first;
Then if you write *first = 20; both arrays will be updated.
There is a problem with your question that you initialize first to 0 and then to 1. If they were the same address then setting to 1 would overwrite the setting to 0.
You question is not self coherent :
you write int* secondArray[4]; : secondArray is an array of 4 pointers to int
you write secondArray[0] = 20 : here secondArray is an array of 4 int values
Hyp 1 : arrays of 4 int values
&secondArray[1] is &secondArray[0] + 1. Full stop. That the way arrays work in C++. In that case if secondArray[0] is the same as firstArray[0] then the 2 arrays are at same address and are in fact the same array and your example becomes :
int firstArray[4];
fill_n(firstArray, 4, 0);
//firstArray values are: 0, 0, 0, 0
/* int secondArray[4]; first elements could not be related and you should have : */
int *secondArray = firstArray;
fill_n(secondArray, 4, 1);
//secondArray values are: 1, 1, 1, 1
//firstArray values are also: 1, 1, 1, 1
Hyp 2 : arrays of 4 pointers
You can have first element of both array point to same value while the three others are independent
int array[5];
int *firstArray[4];
int *secondArray[4];
firstArray[0] = &(array[0]);
for(int i=1; i<4; i++)
firstArray[i] = secondArray[i] = &(array[1]);
}
secondArray[0] = &(array[4]);
Then :
int* firstArray[4];
fill_n(firstArray, 4, 0);
//firstArray values are: 0, 0, 0, 0
int* secondArray[4];
fill_n(secondArray, 4, 1);
//secondArray values are: 1, 1, 1, 1
//firstArray values are: 1, 0, 0, 0
and
*(secondArray[0]) = 20;
//secondArray values would be: 20, 1, 1, 1 (because I just changed it)
//firstArray values would be: 20, 0, 0, 0 (because it's pointing to the value I just changed)
That is what you asked for, but it is a very unusual requirement and I'm not sure it is really what you need.