This question already has answers here:
conversion of 2D array to pointer-to-pointer
(6 answers)
Closed 5 years ago.
how to assign two dimensional array to **pointer ?
this is the idea of what i want to do
int arrray [2][3];
int **pointer = array;
so pointer[0][1]= 1;
so any help ?
thanks in advance
Declare the pointer like this:
int (*pointer)[3] = array;
But this is infinitely nasty in C++. Perhaps you could find a better solution (one involving vectors and whatnot) if you explained what your general purpose is.
The simple answer is that you cannot. A bidimensional array is a contiguous block of memory that holds each line, while a pointer to pointer can refer to a memory location where a pointer to a different memory location containing the integers is.
You can on the other hand create a separate data structure that holds the pointers to the elements in the way you want (i.e. create an array of pointers, initialize those pointers to the beginning of each row, and use a pointer to that array of pointers as pointer), but it is not useful at all, but rather will complicate everything unneedingly.
The question probably comes from the common misconceptions that arrays and pointers are the same, which they are not. An array can decay to a pointer to the first element of the array (and will do so quite often), but the type of that pointer is the type of the first element. In a bidimensional array, the type of the first element is the inner array, not the basic element type.
Related
I want to know whether a pointer is pointing to an array or single integer. I have a function which takes two pointer (int and char) as input and tell whether a pointer is pointing to an array or single integer.
pointer=pointer+4;
pointer1=pointer1+4;
Is this a good idea?
Like others have said here, C doesn't know what a pointer is pointing to. However if you should choose to go down this path, you could put a sentinel value in the integer or first position in the array to indicate what it is...
#define ARRAY_SENTINEL -1
int x = 0;
int x_array[3] = {ARRAY_SENTINEL, 7, 11};
pointer = &x_array[0];
if (*pointer == ARRAY_SENTINEL)
{
// do some crazy stuff
}
pointer = &x;
if (*pointer != ARRAY_SENTINEL)
{
// do some more crazy stuff
}
That's not a good idea. Using just raw pointers there's no way to know if they point to an array or a single value.
A pointer that is being used as an array and a pointer to a single values are identical - they're both just a memory address - so theres no information to use to distinguish between them. If you post what you want to ultimately do there might be a solution that doesn't rely on comparing pointers to arrays and single values.
Actually pointers point to a piece of memory, not integers or arrays. It is not possible to distinguish if an integer is single variable or the integer is an element of array, both will look exactly the same in memory.
Can you use some C++ data structures, std::vector for example?
For C++ questions, the answer is simple. Do not use C-style dynamic arrays in C++. Whenever you need a C-style dynamic array, you should use std::vector.
This way you would never guess what the pointer points to, because only std::vector will be holding an array.
I want to know whether a pointer is pointing to an array or single integer. I have a function which takes two pointer (int and char) as input and tell whether a pointer is pointing to an array or single integer.
pointer=pointer+4;
pointer1=pointer1+4;
Is this a good idea?
Like others have said here, C doesn't know what a pointer is pointing to. However if you should choose to go down this path, you could put a sentinel value in the integer or first position in the array to indicate what it is...
#define ARRAY_SENTINEL -1
int x = 0;
int x_array[3] = {ARRAY_SENTINEL, 7, 11};
pointer = &x_array[0];
if (*pointer == ARRAY_SENTINEL)
{
// do some crazy stuff
}
pointer = &x;
if (*pointer != ARRAY_SENTINEL)
{
// do some more crazy stuff
}
That's not a good idea. Using just raw pointers there's no way to know if they point to an array or a single value.
A pointer that is being used as an array and a pointer to a single values are identical - they're both just a memory address - so theres no information to use to distinguish between them. If you post what you want to ultimately do there might be a solution that doesn't rely on comparing pointers to arrays and single values.
Actually pointers point to a piece of memory, not integers or arrays. It is not possible to distinguish if an integer is single variable or the integer is an element of array, both will look exactly the same in memory.
Can you use some C++ data structures, std::vector for example?
For C++ questions, the answer is simple. Do not use C-style dynamic arrays in C++. Whenever you need a C-style dynamic array, you should use std::vector.
This way you would never guess what the pointer points to, because only std::vector will be holding an array.
I have a class that has a large 2 dimensional array in it. It used to be a dynamic array allocated on the heap and now it is statically sized which I prefer.
private:
int fontTextureCoords_[100][7];
I had to add the type casting to the the accessor in order to return the array for access outside the class which is currently working okay, but I'm not sure it is safe or the correct way to handle this.
public:
inline int **getFontTextureCoords()
{
return (int**)fontTextureCoords_;
}
Is this safe / the correct way to do this or is there a more preferred method for returning a pointer to a multi-dimensional array?
That's not the correct way to do that and shouldn't compile. A 2d array is not convertible to a pointer to pointer. You'd have to return a pointer to an array, which is easiest to write using a typedef:
using T = int[7];
inline T* getFontTextureCoords() { return fontTextureCoords_; }
Although it'd be much better to just return a reference the full array:
using T = int[100][7];
inline T& getFontTextureCoords() { return fontTextureCoords_; }
You could also just std::array<std::array<int, 7>, 100>.
Maybe this diagram shows you the difference between the two types of multi-dimensional array declarations. (Sometime people don't understand this.)
The first one says a is a single block of 100 consecutive 7-int chunks, or 700 ints total, all together in one piece.
The second says a is an array of pointers, where each pointer points to a different chunk of ints, scattered all over memory.
The compiler needs to know this, because if you write a[i][j] it has to generate totally different code.
Casting an array such as int fontTextureCoords_[100][7]; to an int** is not right. It leads to undefined behavior.
If it is not too much, change getFontTextureCoords to:
inline int (*getFontTextureCoords()) [7]
{
return fontTextureCoords_;
}
and use it as:
int (*ptr)[7] = getFontTextureCoords();
If you have the option of using std::vector or std::array, it will be better to use them.
There are no multi-dimensional arrays in C/C++. There are only single dimenstional arrays. You can have a single-dimensional array, with every element of it being another single dimensional array. While there seem to be no difference, it is there and is very important.
This is exactly way transitive logic doesn not work. Everybody has gone through it. 'If single-dimensional arrays are passed as a pointer to the first elelement, 2-D arrays should be passed as a pointer to pointer to first element, etc'. But since it is not a two-dimensional array, but array of arrays, the logic can not be applied.
You can reason about it in the following way. Let's say, you have an array of types X.
X x[10];
How do you access element number 5? Easy -
x[5] = 42;
But what compiler does when it sees it? It does approximately this:
*(&x[0] + 5) = 42;
So it takes the address of the first element, and adds 5 to it to get to the address of your 5th element. But what adding 5 means? In bytes, how many bytes should be skipped from address of beginning of the array to arrive at requested memory location? Of course, 5 * sizeof(X). Now, if you have '2-D' array, declared like this:
X x[2][3];
And you try to work with it through the pointer to pointer:
px = (X**)x;
px[3][4] = 42;
Remember, to genereate the code for [][], compiler needs to express in the way of *(px + ). And something has to be the size of the array (as elements of your array are arrays). But you need to know array size for this, and as you can see, your px does not have any array size encoded in it. The only size it know is size of X, which is not enough.
Hope it makes sense, and explains why you can't use int** instead of x[][].
This question already has answers here:
C pointer to array/array of pointers disambiguation
(13 answers)
Closed 7 years ago.
What is the difference between
int *p1[M][N]
and
int (*p2)[M][N]
Also if we define another such pointer
int (*p3)[M][N][K]
what does this represent?
If anyone can explain the differences between the above three, it will be very helpful.
int *p1[M][N] is a 2D array of pointers.
int (*p2)[M][N] is a pointer to a 2D array.
int (*p3)[M][N][K] is a pointer to a 3D array.
It helps to know that you can read any C declaration using an alternating right-and-left fashion. So the direct answer to your question is:
int *p1[M][N] is an array of arrays of pointers-to-ints.
int (*p2)[M][N] is a pointer to an array of arrays of ints.
int (*p3)[M][N][K] is a pointer to an array of arrays of arrays of integers.
You can think of these using the standard "2D" or "3D" terminology, where a 2D array is a table with the first set of brackets indicating the row and the second set of brackets indicating the column. This is not 100% faithful to the way the computer actually works, but it's a highly effective mental model. But going back to how to decipher complicated C declarations:
You read them boustrophedonically, so first right, then left, then right, then left, and so on. Here's an example.
int * const (*p[30])(int x)
we start at the name being declared, p. We look right to get the size of p, which is 30.
So now we know p is an array of 30 something. So we look left, and we find *, so we know p is an array of 30 pointers to something. So we look right, and find the parentheses, indicating a function. Now we know p is an array of pointers to functions. We can trivially include that the parameters to these functions should be an int x.
So we've run out of things on the right, so we just keep interpreting the left elements.
p is an array of pointers to functions returning... const. There's more on the left, so keep going. p is an array of pointers to functions returning const pointers to int.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is array name a pointer in C?
char arr[1024];
arr++ //move arr to arr+1, error!
I have heard the the name of a char array is a char pointer, is it?
The name of an array decays to an pointer to its first element sometimes.
An expression with array type will convert to a pointer anytime an array type is not legal, but a pointer type is.
You cannot do:
arr++;
Because array is an non modifiable l-value.
An array is a block of memory to which you gave a name.
What does it mean to "increment" it by one? That doesn't make any sense.
A pointer is a memory address. "Incrementing" it by one means to make it point to the element after it.
Hope that makes sense.
Arrays and pointers are not always exchangeable. A more interesting example to illustrate the difference between arrays and pointers is a 2D array:
Consider int **a and int b[3][3].
In the first approach to a 2D array we have a 1D array of pointers to 1D arrays in memory (of course you have to allocate the memory dynamically to use this).
In the second approach of actually using a 2D C array, we have the elements laid out sequentially in memory, and there's no separate location where an array of pointers are stored.
If you try to dereference b, you get a pointer to its first element (i.e. b gets converted to an int (*)[3] type).
nothing, apart from looks..
Well and as you defined the array there you declared already 1024 bytes for the array. Also you obviously can't change the array "base".
An array name is for most (but not all) purposes identical to a constant pointer (not to be confused with a pointer to a constant). Because it's a constant, you cannot modify it with the increment operator ++. There's a good answer explaining this in more detail in an older similar question.