I am teaching myself C++ and and currently learning about multi-dimensional arrays. Below is the code I am using. Below the code are the questions/concepts I am having trouble with.
int main(){
const unsigned row = 4, col = 4;
int arr[row][col], cnt = 0;
for (int(*a)[col] = arr; a != arr + col; ++a){
for (int *b = *a; b != *a + col; ++b){
*b = cnt;
++cnt;
}
}
system("pause");
return 0;
}
in the first line of the for statement for (int(*a)[col] = arr;
a != arr + col; ++a). Why does the int(*a)[col] = arr; require
the [col] for the for loop to execute correctly?
in the first line of the second for statement for (int *b = *a; b != *a + col; ++b). Is *a not dereferencing the pointer?
The second for statement is unclear to me as to how it work. I understand which order it executes, but I am unclear about the relationship between the first for statement and the second for statement. any clarification for would be very helpful.
Pointers have a type that they point to. Except for void *, a pointer can only hold the address of an object of that type.
In the first line: Since you are looping over each row of the array, the pointer must point to a whole row (not to a single int).
In the second line, *a does dereference a. *a. is always equivalent to a[0]. Since a points to a row, a[0] designates that row.
a[0] is an array, so when it is used to initialize b, it decays to a pointer to the first element of that row.
The firs tlook loops over each row; the second loop loops over ech column. It's the same structure as:
for (int i = 0; i < row; ++i)
for (int j = 0; j < row; ++j)
arr[i][j] = ++cnt;
except you are using a pointer instead of an integer offset that is later added to a pointer.
Related
I have a List class for char arrays. And I want to push back N arrays from 'a' to 'a..a'.
char* x;
SList list;
for (unsigned int i = 1; i < n+1; i++) {
x = new char[i+1];
for (unsigned int j = 0; j < i; j++) {
x[j] = 'a';
}
x[i] = '\0';
list.push_back(&x);
}
But every time, x has the same address. And in result, my List object contains N pointers to the same address.
Is there a way to push back these arrays in loop with correct memory allocation?
Before asking found this question, but it doesn't provide a cool solution for my problem.
In each iteration of the loop x = new char[i+1]; returns a different address, which is stored in x. So the value of x changes in each iteration, yet, the address of x doesn't.
Did you mean
list.push_back(x);
to add the address of the newly allocated memory? Of course this would require you to change the type of list the a collection of char *.
It must be mentioned that dereferencing &x after x goes out of scope will lead to undefined behaviour, because x doesn't exist anymore. You fill list with dangling pointers.
Finally I'd like to mention that you could avoid the nasty manual memory management and simply use a std::vector<std::string>.
std::vector<std::string> list;
for (unsigned int i = 1; i < n+1; i++) {
std::string newString(i, 'a'); // string with i times 'a'
list.push_back(newString);
}
Ok. I found a pretty straightforward solution:
char** x = new char*[n];
SList sl;
for (unsigned int i = 0; i < n; i++) {
x[i] = new char[i+1];
for (unsigned int j = 0; j < i; j++) {
x[i][j] = 'a';
}
x[i][i] = '\0';
sl.push_back(&x[i]);
}
With having N addresses to store pointers to arrays. I can just add their addresses to my list object
I would like to determine if there is a way to determine whether a dynamically allocated matrix is square (nxn).
The first thing that came to mind was to see if there is a way to find out whether a pointer is about to point to an invalid memory location. But according to these posts:
C++ Is it possible to determine whether a pointer points to a valid object?
Testing pointers for validity (C/C++)
This cannot be done.
The next idea I came up with was to somehow use the sizeof() function to find a pattern with square matrices, but using sizeof() on a pointer will always yield the same value.
I start off by creating a dynamically allocated array to be of size nxn:
int **array = new int*[n]
for(int i = 0; i < n; i++)
array[i] = new int[n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
array[i][j] = 0;
}
}
Now I have a populated square matrix of size nxn. Let's say I'm implementing a function to print a square 2D array, but a user has inadvertently created and passed a 2D array of size mxn into my function (accomplished by the code above, except there are more row pointers than elements that comprise the columns, or vice versa), and we're also not sure whether the user has passed a value of n corresponding to n rows or n columns:
bool(int **arr, int n){
for(int rows = 0; rows < n; rows++)
for(int cols = 0; cols < n; cols++)
cout << *(*(arr + rows) + cols) << " ";
// Is our next column value encroaching on unallocated memory?
}
cout << endl;
// Is our next row value out of bounds?
}
}
Is there any way to inform this user (before exiting with a segmentation fault), that this function is for printing square 2D arrays only?
Edit: corrected 3rd line from
array[i] = new int[i]
to
array[i] = new int[n]
There is NO way to find out information about an allocation. The ONLY way you can do that, is to store the information about the matrix dimensions somewhere. Pointers are just pointers. Nothing more, nothing less. If you need something more than a pointer, you'll need to define a type that encapsulates all of that information.
class Matrix2D
{
public:
Matrix2D(int N, int M)
: m_N(N), m_M(M), m_data(new int[N*M]) {}
int N() const { return this->m_N; }
int M() const { return this->m_M; }
int* operator[] (int index) const
{ return m_data + m_M * index; }
private:
int m_N;
int m_M;
int* m_data;
};
What's the meaning of the code below?
int **matrix = new int*[n]
What's the difference here between matrix and int*[n]?
It is an array of 'n' pointers, for which memory can be allocated and initialized in loop.
If n is 3, it is an array of 3 elements and each is pointer to int, can point to set of array of integer values like below.
matrix[0] -> Ox001 points to array of int [ 1 2 3 4]
matrix[1] -> Ox017 [ 5 6 7 8]
matrix[2] -> Ox024 [ 9 10 11 12]
Sample code like this
int **m = new int*[3];
for(auto i=0; i < 3; i++)
{
m[i] = new int[3];
for(auto j=0; j < 3; j++)
m[i][j] = 0;
}
for(auto i=0; i < 3; i++)
{
m[i] = new int[3];
for(auto j=0; j < 3; j++)
cout << m[i][j];
cout << "\n";
}
for instance there is cricket team and you need
Since you have Cricket* team;, this indicates you have one of two possible
situations:
1) a pointer to a single CricketPlayer (or any derived) type
2) a pointer to an array of CricketPlayer (but not derived) types.
What you want is a pointer to an array of CricketPlayer or derived types. So you
need the **.
You'll also need to allocate each team member individually and assign them to the array:
// 5 players on this team
CricketPlayer** team = new CricketPlayer*[5];
// first one is a bowler
team[0] = new Bowler();
// second one is a hitter
team[1] = new Hitter();
// etc
// then to deallocate memory
delete team[0];
delete team[1];
delete[] team;
In your query,
It can be understood as
int *matrix[]=new int*[n];
SO there are n pointers pointing to n places.
Because
int *foo;
foo=new int[5];
will also create 5 consecutive places but it is the same pointer.
In our case it is array of pointers
You need to notice some thing as follows:
int *p means that p is a pointer that points to an int variable or points to an array of int variables.
int* *p means that p is a pointer that points to an int* variable or points to an array of int* variables.
new int[5] is an array of 5 int variables.
new int*[5] is an array of 5 int* variables.
In this case, matrix is the second type so it can point to an array of int* variables so the statement:int **matrix = new int*[n] is legal
It means that you have declared a double pointer(of type int) called matrix and allocated an array of n int* pointers. Now you can use matrix[i] as an int* pointer (0 <= i < n). Later you might want to allocate memory to individual pointers as well like matrix[i] = new int[size];(size is an int or more appropriately size_t)
matrix is an object of type int **. This type is a pointer to pointer to int.
On the other hand, int * is a type, a pointer to int.
The expression:
new int*[n]
creates n adjacent objects of type int * somewhere in memory and returns a pointer to the first of them. In other words, it allocates and constructs n pointers to int; and returns a pointer to the first. Since the first (and each of them) are int *, the pointer pointing to the first is, in turn, of type int **.
It would be absolutely clear if you remember the operator associativity and precedence.
Going by that int *[n] will be interpreted by compiler : as array of " n pointer to integers".(as [ ] has greater precedence than *, so for easy understanding, compiler interprets it that way.).
Now comming to other side int ** matrix is pointer to pointer.
When you created an array of pointer,you basically have the address of the first location ,here first location stores an pointer to integer.
So,when you are storing the address of the first address of such array you will need pointer to a pointer to point the whole array.
//code for passing matrix as pointer and returning as a pointer
int ** update(int ** mat)
{
mat[0][1]=3;
return mat;
}
int main()
{ int k=4;
int **mat = new int*[k];
for(auto i=0; i < k; i++)
{
mat[i] = new int[k];
for(int j=0;j<k;j++)
{
if(i==j)
mat[i][j]=1;
else
mat[i][j]=0;
}
}
mat=update(mat);
for(auto i=0; i < k; i++)
{
for(auto j=0; j < k; j++)
cout << mat[i][j];
cout << "\n";
}
return 0;
}
I want to swap two lines in a matrix. My matrix is an allocated solid block of memory.
I have an array of pointers that point to the rows of the matrix. The first pointer points to this big allocated block. And other pointers point to different parts or this block.
If I swap any two rows, except the first, it's OK. But I have problems with the first row.
I guess that's because the pointer to the first row is different from other. But what is the main difference?
#include <iostream>
int** allocateMatrix(int rows, int cols) {
// allocating array of pointers (rows)
int** matrix = new int*[rows];
// allocating one solid block for the whole matrix
matrix[0] = new int[rows*cols];
// setting the pointers for rows
for ( int i = 1; i < rows; ++i ) {
matrix[i] = matrix[i-1] + cols;
}
// fill the matrix with consecutive numbers
int k = 1;
for ( int i = 0; i < rows; ++i ) {
for ( int j = 0; j < cols; ++j ) {
matrix[i][j] = k;
k += 1;
}
}
return matrix;
}
void freeMatrix(int** matrix) {
delete[] matrix[0];
delete[] matrix;
}
int main() {
int n = 3;
int m = 3;
int** matrix = allocateMatrix(n, m);
// swap the first and the second line
int* tmp = matrix[0];
matrix[0] = matrix[1];
matrix[1] = tmp;
// print matrix (it is printing ok)
for ( int i = 0; i < n; ++i ) {
for ( int j = 0; j < m; ++j ) {
std::cout << matrix[i][j] << ' ';
}
std::cout << std::endl;
}
// problem is here
freeMatrix(matrix);
return 0;
}
The main difference is that the first pointer was returned by new[]. Deleting that pointer will deallocate the entire memory block, but deleting any other pointer in the array will have undefined behaviour.
You could store the pointer which you get from new[] separately, and have a duplicate "weak" pointer to the first row that you keep in the array of row pointers.
Your code won't work if you swap first (0) and second (1) rows because you are using matrix[0] to delete the memory allocation.
You need to somehow "keep" the original allocation, e.g.
int *origalloc;
...
origalloc = matrix[0] = new int[rows*cols];
...
delete[] origalloc; // Instead of malloc[0];
What you pass to delete or delete [] must the the same pointer-value as what you get back from the new or new []. Anything else is undefined behaviour.
could someone give me a brief explanation of what is happening differently in the functions below?
void f1(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)[i].ival = i;
}
}
void f2(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)->ival = i;
(*d)++
}
}
void f3(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d->ival = i;
d++;
}
}
void f4(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d[i].ival = i;
}
}
particularly what is happening differently in f2. but clearly different things are happening in each.
f1 and f3 do the same thing (but differently). f2 fails completely, and f4 is buggy (works in this example, but when i tried to put other values into other pointers (char *) the strings end up strange.)
void f1(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)[i].ival = i;
}
}
The d seems to be a pointer to array of data_t's (or is a 1-element array of arrays of data_t). It is dereferenced to recover the array of data_t's and then i-th element of this array is modified.
void f2(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)->ival = i;
(*d)++
}
}
This is a bit tricky and indeed does something different than in the first case. There was a pointer to array of data_t's. Here we have an array of pointers to data_t's. The pointer to first element is dereferenced to retrieve a pointer to data. Then -> is used to access the data and value is modified ( x->y = (*x).y ). Finally the pointer is moved to the next element of main array.
void f3(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d->ival = i;
d++;
}
}
Here we have simpler case, the d is just an array of data_t's accessed by pointer. Inside the loop, an element is accessed by ->, and then d is incremented to point to next element of array.
void f4(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d[i].ival = i;
}
}
Similarly to f3, elements are modified by the [] operator.
Note the following facts:
int[] =(def) int *
if a is of type int * and i is of any integral type, then:
*(a + i) =(def) a[i]
Also, if a points to first element of an array, then
*a =(def) a[0]
and then, after a "a++"
*a =(def) a[1]
...and so on.
Let's take these one at a time:
// f1
(*d)[i].ival = i;
First, (*d) is dereferencing d, which appears to be a pointer to an array of data_t variables. This allows access to the actual array, such that [i] is accessing the i-th element of the array and assigning i to it.
// f2
(*d)->ival = i;
(*d)++;
(*d) is dereferencing d just like in the first one. However, there is one crucial bit of information about arrays that you should understand before moving on...
int j[2] = { 42, 50 };
int j0 = *j; // j0 is now 42
j += 1;
int j1 = *j; // j1 is now 50
Arrays are implemented as individual variables sequentially oriented in "slots" in memory, and an array is really just a pointer to the first slot. As such, *j is dereferencing j, which is currently pointing to the first element, resulting in 42. Doing j += 1 advances the pointer by one "slot", such that *j will now result in 50.
Now, back to f2. (*d)->ival is exactly like doing (**d).ival. This is very much like the simple example I gave above. The next line, (*d)++, is advancing the pointer to the next "slot". Consider this simple diagram of what's "happening" in memory:
+------+------+
|*(j+0)|*(j+1)|
j --->|------|------|
| 42 | 50 |
+------+------+
with j pointing to the first "slot", the dereference shown in the first row, the value in the second.
f3 is very much like f2, except that it expects the array to be passed as an argument, instead of a pointer to it. Hence, d only needs to be dereferenced once with the -> operator (again, exactly like (*d).ival).
f4is very much like f1, except that it expects the array to be passed as an argument, instead of a pointer to it. Hence, d[i] is directly accessing the i-ith element of the array.
void f1(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)[i].ival = i;
}
}
You get a pointer to array **d of data_t ,which element is a structure,having a field ival
Access the array *d
Iterate all array elements,element by element,changing indices i.And updating ival of each array element by to be i
Note:You dont change the pointer*d`,pointing to array beginning
void f2(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)->ival = i;
(*d)++
}
}
You get a pointer to array **d of data_t ,which element is a structure,having a field ival
Access the array *d,which is also a pointer to the array (first element)
Updating ival of the (above) element by to be i,using pointer notation (*d)->ival = i;
Promote the pointer to the next array element (*d)++ and return to 2.From now on *d is
pointing to the "sifted"array beginning.
void f3(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d->ival = i;
d++;
}
}
1.You get an array *d of data_t ,which element is sa structure,having a field ival.
2.It also can be considered you get a pointer to the first element of array.
Access access and update ival to be i,by pointer: d->ival = i;
3.Promote the pointer to the next array element d++
void f4(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d[i].ival = i;
d++;
}
}
As in f3.But you promote indices and update ival using reference notation (by value)