Passing 2D array of structs - c

I'm having difficulty passing a 2D array of structs. The size of the 2D array is dynamic (depends on given input parameters). I get the error:
maze_array.c:76:14: error: incompatible types when assigning to type ‘BlockNode {aka struct BlockNode}’ from type ‘BlockNode * {aka struct BlockNode *}’
Maze[i][j]=myBlockNode;
Here is my code:
int main(int argc, char *argv[]){
int MazeWidth=1;
int MazeHeight=1;
int NumOfAvatars=1;
BlockNode* Maze[MazeWidth][MazeHeight];
InitializeArray(Maze[0],MazeWidth,MazeHeight,NumOfAvatars);
return 1;
}
int InitializeArray(BlockNode** Maze,int MazeWidth, int MazeHeight, int NumOfAvatars){
for (int i=0; i<MazeWidth;i++)
{
for (int j=0; j<MazeHeight;j++)
{
//Initialize a BlockNode
printf("HERE1\n");
BlockNode *myBlockNode;
myBlockNode=calloc(1,sizeof(BlockNode));
myBlockNode->North=0;
myBlockNode->South=0;
myBlockNode->East=0;
myBlockNode->West=0;
int myArray[NumOfAvatars];
memset(myArray,0,sizeof(myArray));
memcpy(myBlockNode->AvatarVisited,myArray,sizeof(myArray));
//Place BlockNode in the Maze
Maze[i][j]=myBlockNode;
}
}
/*
printf("North %d\n", Maze[0][0]->North);
printf("AvatarVisted %d\n", Maze[0][0]->AvatarVisited[0]);
*/
return 1;
}

You should take into account that a 2D array is not equal to pointer to pointer, for example, if you try to compile...
int array[10][10];
int** p=array;
...you would get a similar error.
If you want to pass a 2D array of pointers and use it like AnArray[i][j] = something, you should change the function declaration to...
int InitializeArray( BlockNode* Maze[][MazeHeight]
, int MazeWidth
, int MazeHeight
, int NumOfAvatars )
...or...
int InitializeArray( BlockNode* (*Maze)[MazeHeight]
, int MazeWidth
, int MazeHeight
, int NumOfAvatars )
...and call it like...
InitializeArray( Maze
, MazeWidth
, MazeHeight
, NumOfAvatars );
Also, read this.

You haven't actually asked a question, but I will assume you are seeking an explanation of the compiler error.
Within your function, Maze[i][j] will be of type BlockNode, since it is dereferencing a BlockNode ** (pointer to a pointer to a Blocknode) twice. myBlockNode is of type BlockNode *. That is the cause of the compiler error - there is no valid assignment of the form some_BlockNode = some_pointer_to_BlockNode.
The real problem, however, is that you don't properly understand the difference between pointers and arrays. You'll need to read up on such topics before anyone will be able to offer useful (that will make sense to you) advice on how to do what you want.

Related

Warning: Return from incompatible pointer type

The code below is producing a compiler warning: return from incompatible pointer type. The type I'm returning seems to be the issue but I cant seem to fix this warning.
I have tried changing the type of hands to int *. Also have tried returning &hands.
int * dealDeck(int numPlayers, int numCards, int cardDeck[])
{
static int hands[MAX_PLAYERS][MAX_CARDS]={0};
int start = 0;
int end = numCards;
int player, hand, j;
int card;
for(player = 0; player < numPlayers; player++)
{
for(hand = start, j=0; hand < end; hand++,j++)
{
card = cardDeck[hand];
hands[player][j] = card;
}
start = end;
end += numCards;
}
return hands;
}
This function should return a pointer to the array "hands". This array is then passed to another function which will print out its elements.
The hands variable is not an int * this is a int **
So you need to return a int **
This is a 2d array.
First of all, you have declared return type of int *, which would mean, that you are trying to return an array, while you want to return a 2-dimensional array. The proper type for this would usually be int **, but that won't cut it here. You opted to go with static, fixed size array. That means, that you need to return pointer to some structures of size MAX_CARDS * sizeof(int) (and proper type, which is the real problem here). AFAIK, there is no way to specify that return type in C*.
There are many alternatives though. You could keep the static approach, if you specify only up to 1 size (static int *hands[MAX_PLAYERS] or static int **hands), but then you need to dynamically allocate the inner arrays.
The sane way to do it is usually "call by reference", where you define the array normally before calling the function and you pass it as a parameter to the function. The function then directly modifies the outside variables. While it will help massively, with the maintainability of your code, I was surprised to find out, that it doesn't get rid of the warning. That means, that the best solution is probably to dynamically allocate the array, before calling the function and then pass it as an argument to the function, so it can access it. This also solves the question of whether the array needs to be initialized, and whether = {0} is well readable way to do it (for multidimensional array) , since you'll have to initialize it "manually".
Example:
#include <stdio.h>
#include <stdlib.h>
#define PLAYERS 10
#define DECKS 20
void foo(int **bar)
{
bar[0][0] = 777;
printf("%d", bar[0][0]);
/*
* no point in returning the array you were already given
* but for the purposes of curiosity you could change the type from
* void to int ** and "return bar;"
*/
}
int main()
{
int **arr;
arr = malloc(sizeof(int *) * PLAYERS);
for (size_t d = 0; d < DECKS; d++) {
/* calloc() here if you need the zero initialization */
arr[d] = malloc(sizeof(int) * DECKS);
}
foo(arr);
return 0;
}
*some compilers call such type like int (*)[20], but that isn't valid C syntax

Incompatible pointer array 2D

Im new with C and i have to do a program for school.
I have 3 classes:
lab11.c(main)
procs.c
procs.h
Im getting this error everytime:
error: conflicting types for 'transposarMatriu'|
\procs.h|171|note: previous declaration of 'transposarMatriu' was here|
My code (main):
char matriu_ori[T_DIM_MAX][T_DIM_MAX];
char matriu_dst[T_DIM_MAX][T_DIM_MAX]
transposarMatriu(matriu_ori, *matriu_dst, mida, mida);
Procs.h
extern void transposarMatriu(char matriu_ori[][T_DIM_MAX], char matriu_dst[][T_DIM_MAX], int nfiles, int ncols);
Procs.c
void transposarMatriu(char matriu_ori[][T_DIM_MAX], char *matriu_dst[][T_DIM_MAX], int nfiles, int ncols) {
int c,d;
for (c = 0; c < nfiles; c++) {
for( d = 0 ; d < ncols ; d++ ) {
*matriu_dst[d][c] = matriu_ori[c][d];
}
}
}
The problem comes from the discrepancy between the function definition in procs.c and its declaration in procs.h.
Procs.h
extern void transposarMatriu(char matriu_ori[][T_DIM_MAX], char matriu_dst[][T_DIM_MAX], int nfiles, int ncols);
The function signature must be identical, in this case is not, as you can see, in procs.c the second argument is of type char*, instead of char as in procs.h.
Procs.c
void transposarMatriu(char matriu_ori[][T_DIM_MAX], char *matriu_dst[][T_DIM_MAX], int nfiles, int ncols) {
...
TL;DR: remove the asterisk in lab11.c and procs.c: transposarMatriu([...] *matriu_dst [...])
The function definition for transposarMatriu in procs.c declares matriu_dst to be of type array of arrays of pointers to char (*matriu_dst[][]) (see C Right-Left Rule if you want to learn to decipher C declarations). Probably not what you intended and it's also a mismatch from the function declaration in procs.h.
I assume you intended matriu_dst to be "modifiable" like in call-by-reference, but there's no need to. Arrays are passed to functions by address, so they're "modifiable" by default.
By the same reasoning, there's no need to dereference matriu_dst in main.c (apply the * operator). In fact, doing so means you're passing the first element of the array to the function (an array of chars).

How to correctly pass a pointer to an array of pointers?

In my code I need to pass a pointer to an array of pointers as a function argument. Code snippets:
struct foo * foos[] = {NULL, NULL, NULL};
some_function(&foos);
and:
static void some_function(struct foo ** foos) {
foos[0] = get_a_foo();
/* some more code here */
}
This works as expected (after some_function() returns, foos[] contains the pointers I set there), but I get a compiler warning for the call to some_function():
note: expected ‘struct foo **’ but argument is of type ‘struct foo * (*)[3]’
What’s the correct way to accomplish what I want (i.e. pass a pointer to the array of pointers to the function, so that the function can change pointers in the array)?
Pass it as some_function(foos)
struct foo ** is a pointer to a (single) pointer to a struct foo, not a pointer to an array of pointers, hence the compiler warning.
An easy way to silence the compiler warning is to call the function as follows:
some_function(&foos[0]);
This will pass a pointer to the first member, i.e. a struct foo **, rather than to the whole array; the address is the same in both cases.
If I understand what you are trying to do (fill your array of pointers with a call to a function), then your understanding of how to accomplish that is a bit unclear. You declare foos, which itself is an array. (an array of what? pointers).
You can treat it just like you would treat an array of char (from the standpoint that you can simply pass the array itself as a parameter to a function and operate on the array within a function) You can do that and have the changes visible in the caller because despite the array address itself being a copy in the function, the values it holds (the individual pointer address) remains the same.
For example:
#include <stdio.h>
char *labels[] = { "my", "dog", "has", "fleas" };
void fillfoos (char **f, int n)
{
int i;
for (i = 0; i < n; i++)
f[i] = labels[i];
}
int main (void) {
char *foos[] = { NULL, NULL, NULL };
int i, n = sizeof foos / sizeof *foos;
fillfoos (foos, n);
for (i = 0; i < n; i++)
printf ("foos[%d] : %s\n", i, foos[i]);
return 0;
}
Above foos is simply treated as an array passed to the function fillfoos which then loops over each pointer within foos filling it with the address to the corresponding string-literal contained in labels. The contents of foos is then available back in main, e.g.
Example Use/Output
$ ./bin/fillptp
foos[0] : my
foos[1] : dog
foos[2] : has
If I misunderstood your question, please let me know and I'm happy to help further.
You need a pointer to an array as clearly mentioned in the warning.
Below is a minimal code sample that explains the same.
#include<stdio.h>
typedef struct foo{
}FOO;
static void some_function(FOO* (*foos)[]) {
// foos above is a pointer to an array of pointers.
// Refer the link to start with a simple example.
// Access it like foos[0][0] which is the same as (*foos)[0]
/* some more code here */
}
int main(int argc, char **argv) {
FOO* foos[]={0,0,0}; // Here you have an array of pointers
some_function(&foos);
}

Passing arrays into functions

hi I'm attempting to create a program that accepts a 7 element array as an argument and returns the third through fifth element of that array to a smaller array however i'm currently getting this error
assign8p7.c: In function 'main':
assign8p7.c:18:2: warning: passing argument 1 of 'copysect' makes pointer from
integer without a cast [enabled by default]
assign8p7.c:3:6: note: expected 'int *' but argument is of type 'int'
from what i can tell the warning has a problem with me passing it an array in the arguments does anyone know how i might fix this? also any other advice for my code is welcome.
#include <stdio.h>
int *copysect(int ar[],int start,int end)
{
int i;
static int retar[3];
for(i = 0; i<3;i++)
{
retar[i+start]=ar[i+start];
}
return retar;
}
int main(int argc, char const *argv[])
{
int arry[7] = {1,2,3,4,5,6,7};
int miniarry[3];
miniarry[0] = *copysect(arry[0],3,5);
return 0;
}
int *copysect(int ar[],int start,int end)
Okay, copysect takes as its first parameter an array of integers.
miniarry[0] = *copysect(arry[0],3,5);
Oops, you passed it a single integer instead of an array.
You are calling the function copysect with the first element in the array, not the pointer to the array. The correct call is:
copysect(arry,3,5);
You could calculate the difference of the array dynamically. Now the caller of copysect function has to know that the difference between start and end is 2.
int retar[end - start + 1]
The assignment in the for loop is wrong. You are dereferencing a value that is out of scope of retar array
retar[i]=ar[i+start];
When calling the copysect function, you are assigning only the first element in the miniarry by dereferencing the array that the function returns, instead of the whole array.
It's not the best idea to have a static array in a function (that would be problematic if you called the function more than once, etc). Instead, you could declare the smaller array elswhere and pass it as a parameter to the function.
void copysect(int ar[], int retar[], int start,int end, )

How do I realloc an array of function pointers?

Straight to the code:
#define PRO_SIGNAL( func, param ) (*func)(param)
void PRO_SIGNAL( paint[0], Pro_Window* );
signal->paint = realloc( signal->paint, sizeof( void (*)(Pro_Window*) ) * signal->paint_count );
The Error:
error: incompatible types when assigning to type 'void (*[])(struct Pro_Window *)' from type 'void *'|
It appears that you are assigning to an array not a pointer.
From your output error message:
'void (*[])(struct Pro_Window *)' from type 'void *'|
Note the [] in there (and it certainly isn't a lambda!) rather than a *
If this is an "extendable" struct you need to realloc the entire struct not just the array member.
By the way, a tip: if realloc fails it returns a NULL pointer and if you assign it to the variable that was being realloc'ed, the original memory it was pointing to will be lost forever. So always realloc into a temp first, check the value, and then assign back to the original pointer if it worked.
You don't show us the definition of singal->paint, but I infer from the error message that it's declared as an array of function pointers, meaning signal is a struct with a flex array (paint[]). You can't assign to an array, you need to realloc the whole struct.
Not sure what you're trying to do, but this works perfectly here:
#include <stdlib.h>
int main(int argc, char ** argv)
{
void (**foobar) (int a, int b);
void (**tmp) (int a, int b);
foobar = NULL;
if (!(foobar = malloc(sizeof(*foobar)*4))
return 1;
if (!(tmp = realloc(foobar, sizeof(*foobar)*5)) {
free(foobar);
return 1;
} else {
foobar = tmp;
}
free(foobar);
return 0;
}
So, either you're trying to realloc an array like Kevin says, or perhaps you're compiling in C++ mode, where I believe that the cast is not implicit.
Edit: I've added some error handling.

Resources