This question already has answers here:
Why can't we use double pointer to represent two dimensional arrays?
(6 answers)
Closed 7 years ago.
I know it's very basic but I MUST understand the concept, why it doesn't work?
void printMat(int arr[N][N], int n)
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (i < j)
{
arr[i][j] = 0;
}
{
arr[i][j] = i+j+2;
}
}
int** triDown(int arr[N][N], int n)
{
int i, j, **a;
for(i = 0; i < n; i++)
{
*(a+i) = (int*)malloc(sizeof(int)*(i+1));
}
for(i=0;i<n;i++)
for(j=0;j<i+1;j++)
{
a[i][j] = arr[i][j];
}
return a;
}
void main()
{
int *arr[N],**NewMat;
printMat(arr,N);
NewMat = triDown(arr,N);
}
I'm having a really hard time trying to understand the pointer-to-pointer thing when it comes to functions and dynamic allocations.
What should've been done in NewMat func?
int a[N][N] and int *a[N] are never compatible. The first is a two-dimensional array of int values, while the second is a one-dimensional array of int pointers. You need to declare it as int (*a)[N] for a compatible pointer type. Then you can pass it an int a[N][N] as an argument, just as you would in the one-dimensional case where you pass an int a[N] to an int *a.
But you need to declare the actual array in main, not just a pointer to it. Note that int (*a)[N] is only a single pointer value, so its size will most likely be 4 or 8 depending on your architecture.
Related
This question already has answers here:
Why can't we use double pointer to represent two dimensional arrays?
(6 answers)
Closed 13 days ago.
I wrote this program that is supposed to sort NxN array. It gets compiled but doesn't work because the pointer type is incompatible.
I just need help with the pointers as argument. I get incompatible pointer type warning for both functions swap and dblArraySort. Any idea why is that ?
thanks in advance !
#include <stdio.h>
#include <stdlib.h>
void
swap(int **a, int **b)
{
int temp;
temp = **a;
**a = **b;
**b = temp;
}
void
dblArraySort(int **dblArray, int arrLen)
{
int chkIndex;
int i, j, k;
for (i = 0; i < arrLen; i++) {
if ((i + 1) % 2 == 0) {
for (j = 0; j < arrLen; j++) {
chkIndex = dblArray[i][j];
for (k = 1; k + j < arrLen; k++)
if (chkIndex < dblArray[i][k + j])
swap(&dblArray[i][j], &dblArray[i][k + j]);
else
continue;
}
} else {
for (j = 0; j < arrLen; j++) {
chkIndex = dblArray[i][j];
for (k = 1; k + j < arrLen; k++)
if (chkIndex >= dblArray[i][k + j])
swap(&dblArray[i][j], &dblArray[i][k + j]);
else
continue;
}
}
}
}
int
main()
{
unsigned int arrayLength;
printf("Provide array size: \n");
scanf("%d", &arrayLength);
int doubleArray[arrayLength][arrayLength];
for (int i = 0; i < arrayLength; i++) {
for (int j = 0; j < arrayLength; j++) {
scanf("%d", &doubleArray[i][j]);
}
}
dblArraySort(doubleArray, arrayLength);
for (int i = 0; i < arrayLength; i++) {
for (int j = 0; j < arrayLength; j++) {
printf("%d ", doubleArray[i][j]);
}
printf("\n");
}
return 0;
}
I tried the code mentioned above
Arrays in C can be confusing. The thing you need to worry about is element type.
The element type of int ** dblArray is int *. In other words, dblArray is an array of int *s.
However, the element type of int doubleArray[arrayLength][arrayLength] is int row_type[arrayLength]. That is not an int *, that is an array, which is a totally different thing.
Moreover, when you use an array⟶pointer conversion, as happens when you say:
dblArraySort(doubleArray, arrayLength); // doubleArray is converted to a pointer
You get a pointer to the array, which in this case is a pointer to the innermost element type, an int — which is also not an int *.
tl;dr: You are trying to pass an array of array of int to a function taking an array of pointer to int. That won’t work.
I would like to comment on your variable naming as well. When you say “double” or “dbl”, as in doubleArray and dblArray the very first thing people will think is that you are handling a linear array of type double, which is also not what the array is.
You have there a two-dimensional array. Not a “double” array. Common naming for such thing would be array2D or matrix.
To make it work you need either C11, which allows you to pass a VLA as:
void sort_array2D( size_t rows, size_t columns, int array[rows][columns] )
{
...
int value = array[i][j];
...
}
int main(void)
{
int array2D[Array_Length][Array_Length];
...
sort_array2D( Array_Length, Array_Length, array2D );
Or you need to simply assume you must compute the index manually. A little function will help:
size_t index2D( size_t rows, size_t columns, size_t r, size_t c )
{
(void)rows; // (quiet the compiler about not using this argument)
return r * columns + c;
}
Then you can write your function as:
void sort_array2D( int * array, size_t rows, size_t columns )
{
...
int value = array[index2D( rows, columns, i, j )];
...
}
int main(void)
{
int array2D[Array_Length][Array_Length];
...
sort_array2D( (int *)array2D, Array_Length, Array_Length );
I haven’t bothered to analyze your sort function. It doesn’t look right to me, but honestly, I’ve barely glanced at it. Calling a value from the array chkIndex looks fishy, since the values of the array are not indices per se, at least not in the context of sorting them.
Remember, when messing with arrays in C you need to keep strict care to not mix up the type of the elements. (Or the types of things in general, whether syntactic or conceptual.)
Consider the following code:
int main(void) {
int *x[5];
for(int i = 0; i < 5; i++) {
x[i] = malloc(sizeof(int) * 5);
}
for(int i = 0; i < 5; i++) {
for(int j = 0; j < 5; j++) {
x[i][j] = i * j;
}
}
modify(x, 5, 5);
return 0;
}
Which of the implementations of method modify below set all elements of the matrix x to zero?
void modify(int **x, int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
x[i][j] = 0;
}
}
}
void modify(int *x[], int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
x[i][j] = 0;
}
}
}
void modify(int x[5][5], int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
x[i][j] = 0;
}
}
}
I'm quite confused about why the third option is not correct. Is there a difference between passing an array located in stack and an array located in heap?
The compiler gives a pretty good clue:
~$ gcc mat.c
mat.c: In function ‘main’:
mat.c:22:12: warning: passing argument 1 of ‘modify’ from incompatible pointer type [-Wincompatible-pointer-types]
modify(x, 5, 5);
^
mat.c:3:17: note: expected ‘int (*)[5]’ but argument is of type ‘int **’
void modify(int x[5][5], int m, int n) {
~~~~^~~~~~~
The declaration int x[5][5] declares an array of arrays. That's something completely different from int *x[5]; which declares an array of pointers. Fun fact: Add parenthesis like this int (*x)[5] and you will instead get a pointer to an int array of size 5. Here is a good site that translates C declarations to English: https://cdecl.org/
Is there a difference between passing an array located in stack and an array located in heap?
Dynamically allocated memory usually ends up on the heap, while the rest usually goes to the stack. However, this is just an implementation detail, and nothing in the C standard requires either a heap or a stack to exist at all.
When you're passing an array to a function it will decay to a pointer to it's first element. The function will have no idea of where the data is (hmmm, well since the pointer has the actual address it does, but it does not know about heap or stack) or how it was allocated. So consider this code snippet:
void setToZero(int * arr, int size) {
for(int i=0; i<size; i++) arr[i] = 0;
}
The function will have EXACTLY the same effect for both x and y:
int x[10];
int *y = malloc(10 * sizeof *y);
setToZero(x);
setToZero(y);
It may help to recall that there are no arrays in C, only pointers and blocks of memory. The rest is compiler fakery.
Your main program allocates a block of memory for 5 *int pointers (called x) on the stack and 5 blocks of 5 ints on the heap. It calls the function with a pointer to the beginning of x, and relies on the function to perform the correct pointer arithmetic to access the other blocks correctly.
The first two functions are equivalent in this case (that's not always true), and the pointer arithmetic correctly matches the allocations. The third function incorrectly performs pointer arithmetic to address 25 ints arranged 5x5, so the first 5 stores overwrite a *int by an int and the 6th access is out of bounds (assuming int and *int are the same size).
I've explained it this way to emphasise the necessity to understand the relationship between arrays and pointer arithmetic in C. If you really understand this you won't need to ask questions like this again.
This question already has answers here:
How do I correctly set up, access, and free a multidimensional array in C?
(5 answers)
Closed 6 years ago.
This is were I got so far,but I don't know if it's right.
This function receives the dimensions of the 2D array (nxn),and allocates it.
flightInfo is the name of the struct.
Will this work?
thanks in advanced
after allocating the array(ignore the method ,since we are not allowed to use the method you proposed) I would like to initialize the struct (I built a function to do it but it didn't work),I tried to do it right after the allocation and kept getting the" Unhandled exception" warning, does it has to do
with the syntax, am I forgetting a '*'?
void flightMatrix()
{
FILE * fpf;
int checkScan,Origin,Dest;
float time,cost;
char flightName[3];
flightInfo *** matrix;
if(!(fpf=fopen("flights.txt","r")))exit(1);
while((checkScan=fscanf(fpf,"%*10c%3d%3d%3c%5f%7f%*",&Origin,&Dest,flightName,&time,&cost))!=EOF)
{
matrix=allocateMatrix(Dest);
matrix[Origin-1][Dest-1]->o=Origin;
}
}
flightInfo*** allocateMatrix(int n)
{ int i,j;
flightInfo*** matrix;
matrix=(flightInfo***)malloc(sizeof(flightInfo **)*n);
for(i=0;i<n;i++)
matrix[i]=(flightInfo **)malloc(sizeof(flightInfo*)*n);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
matrix[i][j] = NULL;
}
return matrix;
}
[http://i.stack.imgur.com/MFC7V.png]
this is what happens when I try to initialize
Technically speaking, this won't create 2D array. The result will be array of pointers, where each one points to different array of pointers to a struct.
The difference is that, memory will be fragmented, so every element will point to some memory location, instead of single continuous memory block.
The common approach for this is to create flatten 2D array:
flightInfo** allocateMatrix(int n)
{
flightInfo** matrix = malloc(n*n * sizeof(*matrix));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
matrix[i*n + j] = NULL;
return matrix;
}
If you are forced to use two indices, then you could place matrix as function argument:
void allocateMatrix(int n, flightInfo* (**matrix)[n])
{
*matrix = malloc(n * sizeof(**matrix));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
(*matrix)[i][j] = NULL;
}
The second asterisk is required, because pointers are passed by value, otherwise you would end up with modified local copy of the pointer, that does nothing to matrix from main function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct flightInfo {
char airport[30];
int altitude;
} flightInfo;
void allocateMatrix(int n, flightInfo* (**matrix)[n])
{
*matrix = malloc(n * sizeof(**matrix));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
(*matrix)[i][j] = NULL;
}
int main()
{
int n = 10;
flightInfo* (*matrix)[n];
allocateMatrix(n, &matrix);
matrix[0][0] = malloc(sizeof(flightInfo));
strcpy(matrix[0][0]->airport, "Heathrow");
matrix[0][0]->altitude = 10000;
printf("%s, %d\n", matrix[0][0]->airport, matrix[0][0]->altitude);
}
The another way would be to encapsulate the array within a struct.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Passing a pointer representing a 2D array to a function in C++
I am trying to pass my 2-dimensional array to a function through pointer and want to modify the values.
#include <stdio.h>
void func(int **ptr);
int main() {
int array[2][2] = {
{2, 5}, {3, 6}
};
func(array);
printf("%d", array[0][0]);
getch();
}
void func(int **ptr) {
int i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
ptr[i][j] = 8;
}
}
}
But the program crashes with this. What did I do wrong?
Your array is of type int[2][2] ("array of 2 array of 2 int") and its name will decay to a pointer to its first element which would be of type int(*)[2] ("pointer to array of 2 int"). So your func needs to take an argument of this type:
void func(int (*ptr)[2]);
// equivalently:
// void func(int ptr[][2]);
Alternatively, you can take a reference to the array type ("reference to array of 2 array of 2 int"):
void func(int (&ptr)[2][2]);
Make sure you change both the declaration and the definition.
It crashes because an array isn't a pointer to pointer, it will try reading array values as if they're pointers, but an array contains just the data without any pointer.
An array is all adjacent in memory, just accept a single pointer and do a cast when calling the function:
func((int*)array);
...
void func(int *ptr) {
int i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
ptr[i+j*2]=8;
}
}
}
How do I feed an array of pointers as an argument to a function?
In the code below, if I want my function f to take an array of pointers int *x[], how should I declare x in main() and feed it as argument to f?
void f(int *x[]){
int data[5] = {1,2,3,4,5};
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
int main(){
int *(x[]), k, l=5;
f(x); // this does not work
for(k=0; k<l; k++){
printf("x[%d] = %d\n", k, *x[k]);
}
}
return 0;
}
Writing f(x) does not work, and neither does f(x[]) or f(x[5]).
In fact, the declaration int *(x[]) is already not recognized by my compiler, while I thought that one could declare an array of pointers without specifying the length of the array.
In main, change
int *(x[])
to
int *x[SIZE]; // SIZE is array size
Note that, you can't declare a zero size array in C except when it is a last member of a structure.
After all, your code will invoke undefined behavior because the variable data is an automatic local variable and will not exist after function returns.
You may want this:
void f(int *x[]){
int *data = malloc(5*sizeof(int);
int temp[5] = {1,2,3,4,5};
memcpy(data, temp, 5*sizeof(int));
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
First of all your code has no sense because you are trying to fill an array of pointers that will point to local variables. That is after exiti8ng the function all pointers will be invalid because original objects will be already destroyed.
The code could have a sense if the array in the function would have static storage duration
void f(int *x[]){
static int data[5] = {1,2,3,4,5};
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
In main array x should be defined at least as
int * x[5];
int main(){
int * x[5], k;
f(x);
for ( k=0; k < 5; k++ ){
printf("x[%d] = %d\n", k, *x[k]);
}
}
return 0;
}
An alternate way to declare an array of pointer as a parameter is to use a pointer of pointer
void f(int **x, int size){
//code
}
However, you'll have to pass the size as a second argument if you want to avoid an overflow.
To call the code you'll just have to do something like this :
int *a[] = { NULL, NULL, NULL};
f(a, 3);