//defines an array of 280 pointers (1120 or 2240 bytes)
int *pointer1 [280];
//defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
int (*pointer2)[280]; //pointer to an array of 280 integers
int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers
Using pointer2 or pointer3 produce the same binary except manipulations as ++pointer2 as pointed out by WhozCraig.
I recommend using typedef (producing same binary code as above pointer3)
typedef int myType[100][280];
myType *pointer3;
Note: Since C++11, you can also use keyword using instead of typedef
using myType = int[100][280];
myType *pointer3;
in your example:
myType *pointer; // pointer creation
pointer = &tab1; // assignation
(*pointer)[5][12] = 517; // set (write)
int myint = (*pointer)[5][12]; // get (read)
Note: If the array tab1 is used within a function body => this array will be placed within the call stack memory. But the stack size is limited. Using arrays bigger than the free memory stack produces a stack overflow crash.
The full snippet is online-compilable at gcc.godbolt.org
int main()
{
//defines an array of 280 pointers (1120 or 2240 bytes)
int *pointer1 [280];
static_assert( sizeof(pointer1) == 2240, "" );
//defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
int (*pointer2)[280]; //pointer to an array of 280 integers
int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers
static_assert( sizeof(pointer2) == 8, "" );
static_assert( sizeof(pointer3) == 8, "" );
// Use 'typedef' (or 'using' if you use a modern C++ compiler)
typedef int myType[100][280];
//using myType = int[100][280];
int tab1[100][280];
myType *pointer; // pointer creation
pointer = &tab1; // assignation
(*pointer)[5][12] = 517; // set (write)
int myint = (*pointer)[5][12]; // get (read)
return myint;
}
Answer from oHo on Stack Overflow//defines an array of 280 pointers (1120 or 2240 bytes)
int *pointer1 [280];
//defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
int (*pointer2)[280]; //pointer to an array of 280 integers
int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers
Using pointer2 or pointer3 produce the same binary except manipulations as ++pointer2 as pointed out by WhozCraig.
I recommend using typedef (producing same binary code as above pointer3)
typedef int myType[100][280];
myType *pointer3;
Note: Since C++11, you can also use keyword using instead of typedef
using myType = int[100][280];
myType *pointer3;
in your example:
myType *pointer; // pointer creation
pointer = &tab1; // assignation
(*pointer)[5][12] = 517; // set (write)
int myint = (*pointer)[5][12]; // get (read)
Note: If the array tab1 is used within a function body => this array will be placed within the call stack memory. But the stack size is limited. Using arrays bigger than the free memory stack produces a stack overflow crash.
The full snippet is online-compilable at gcc.godbolt.org
int main()
{
//defines an array of 280 pointers (1120 or 2240 bytes)
int *pointer1 [280];
static_assert( sizeof(pointer1) == 2240, "" );
//defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
int (*pointer2)[280]; //pointer to an array of 280 integers
int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers
static_assert( sizeof(pointer2) == 8, "" );
static_assert( sizeof(pointer3) == 8, "" );
// Use 'typedef' (or 'using' if you use a modern C++ compiler)
typedef int myType[100][280];
//using myType = int[100][280];
int tab1[100][280];
myType *pointer; // pointer creation
pointer = &tab1; // assignation
(*pointer)[5][12] = 517; // set (write)
int myint = (*pointer)[5][12]; // get (read)
return myint;
}
Both your examples are equivalent. However, the first one is less obvious and more "hacky", while the second one clearly states your intention.
int (*pointer)[280];
pointer = tab1;
pointer points to an 1D array of 280 integers. In your assignment, you actually assign the first row of tab1. This works since you can implicitly cast arrays to pointers (to the first element).
When you are using pointer[5][12], C treats pointer as an array of arrays (pointer[5] is of type int[280]), so there is another implicit cast here (at least semantically).
In your second example, you explicitly create a pointer to a 2D array:
int (*pointer)[100][280];
pointer = &tab1;
The semantics are clearer here: *pointer is a 2D array, so you need to access it using (*pointer)[i][j].
Both solutions use the same amount of memory (1 pointer) and will most likely run equally fast. Under the hood, both pointers will even point to the same memory location (the first element of the tab1 array), and it is possible that your compiler will even generate the same code.
The first solution is "more advanced" since one needs quite a deep understanding on how arrays and pointers work in C to understand what is going on. The second one is more explicit.
How to pass a 2D array by pointer in C? - Stack Overflow
How to get a pointer to 2D array when writing a C source Mex file?
c - Pointer to 2D Array
pointer to 2d array - C++ Forum
I know that I can go from one of the types 'char [1]' and 'char *' to the other. However, it seems not as easy with 'char [1][1]' and 'char **'.
In my main function I have
`char a[1][1];`
`a[0][0] = 'q';`
`printf("a: %p\n", a);`
`printf("*a: %p\n", *a);`
`printf("**a: %p\n", **a);`I'm of course compiling with warnings and I know that gcc complains about the 5'th line as **a is actually of type char and not a pointer type. However running the code shows that 'a' and '*a' are actually the same pointer but '**a' is as expected something else (0x71 which I assume is related to 'q' in some way).
I'm trying to make sense of this and it seems that because *a and a are equal **a must also be equal to a because **a=*(*a)=*(a)=*a=a. It seems that the only error in this reasoning can be the types of a, *a, **a.
How is 'a' actually stored in memory? If 'a' is a pointer to another memory location (in my case 0x7fff9841f250) then surely *a should be the value at that memory address which in my case is also 0x7fff9841f250. So then **a would be the value at 0x7fff9841f250 which is the same value as 'a'... It seems that I cannot view the 2d array 'char a[1][1]' as pointers in a way that makes sense. But then how can I think of this type? What is the type and what does a, *a, **a, a[0], a[0][0] actually mean?
Can anyone help me make sense of this?
char ** doesn't represent a 2D array - it would be an array of pointers to pointers. You need to change the definition of printarray if you want to pass it a 2D array:
void printarray( char (*array)[50], int SIZE )
or equivalently:
void printarray( char array[][50], int SIZE )
In main(), the variable "array" is declared as
char array[50][50];
This is a 2500 byte piece of data. When main()'s "array" is passed about, it is a pointer to the beginning of that data. It is a pointer to a char expected to be organized in rows of 50.
Yet in function printarray(), you declare
char **array
"array" here is a pointer to a char *pointer.
@Lucus suggestion of void printarray( char array[][50], int SIZE ) works, except that it is not generic in that your SIZE parameter must be 50.
Idea:
defeat (yeech) the type of parameter array in printarray()
void printarray(void *array, int SIZE ){
int i;
int j;
char *charArray = (char *) array;
for( j = 0; j < SIZE; j++ ){
for( i = 0; i < SIZE; i ++){
printf( "%c ", charArray[j*SIZE + i] );
}
printf( "\n" );
}
}
A more elegant solution is to make the "array" in main() an array of pointers.
// Your original printarray()
void printarray(char **array, int SIZE ){
int i;
int j;
for( j = 0; j < SIZE; j++ ){
for( i = 0; i < SIZE; i ++){
printf( "%c ", array[j][i] );
}
printf( "\n" );
}
}
// main()
char **array;
int SIZE;
// Initialization of SIZE is not shown, but let's assume SIZE = 50;
// Allocate table
array = (char **) malloc(SIZE * sizeof(char*));
// Note: cleaner alternative syntax
// array = malloc(sizeof *array * SIZE);
// Allocate rows
for (int row = 0; row<SIZE; row++) {
// Note: sizeof(char) is 1. (@Carl Norum)
// Shown here to help show difference between this malloc() and the above one.
array[row] = (char *) malloc(SIZE * sizeof(char));
// Note: cleaner alternative syntax
// array[row] = malloc(sizeof(**array) * SIZE);
}
// Initialize each element.
for (int row = 0; row<SIZE; row++) {
for (int col = 0; col<SIZE; col++) {
array[row][col] = 'a'; // or whatever value you want
}
}
// Print it
printarray(array, SIZE);
...
To access the address of group1 pass it to the pointer in this way:
int *gPtr1 = &group1[0][0];
Using that it's easy to find the soultions: 1 and 2.
The correct records will look like
int ( *gPtr1 )[3] = group1;
int ( *gPtr2 )[3] = group2;
And these expressions
*(gPtr1 + 3)
*(gPtr2 + 3)
are trying to access the memory after the last elements of the arrays because the arrays have only three rows. That is the type of expression *(gPtr1 + 3) is int[3] and there are only three such elements in the oridinal arrays.
or you could write
int *gPtr1 = ( int * )group1;
int *gPtr2 = ( int * )group2;
In this case using the pointers the arrays are interpretated as one-dimensional arrays with 9 elements and expressions
*(gPtr1 + 3)
*(gPtr2 + 3)
will return correspondingly
1
2