Incompatible pointer array 2D - c

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).

Related

How to fix "conflicting types" for a function and its declaration?

I want to pass a two-dimensional char array to a function but don't know how to declare the function before the main(). The function compiles and works well before I declare it. But after I declare it, I encounter compiling issues.
I'm using EMACS on MacBook pro. The compiler is gcc.I tried to declare my function print string various ways including
void printstring(int, int,char **);
or
void printstring(int, int,char *);
But none of them work. My Full codes are:
#include<stdio.h>
#include<stdlib.h>
void printstring(int, int,char **);
int main(){
char word[3][6]= {"hello","world","I"};
printstring(3,6,word);
return 0;
}
void printstring(int n, int m, char (*w)[m]){
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
I expected that there is no compiling error but I got one error and one warning. Details can be found below:
test.c: In function 'main':
test.c:9:19: warning: passing argument 3 of 'printstring' from incompatible pointer type [-Wincompatible-pointer-types]
printstring(3,6,word);
^~~~
test.c:5:6: note: expected 'char **' but argument is of type 'char (*)[6]'
void printstring(int, int,char **);
^~~~~~~~~~~
test.c: At top level:
test.c:13:6: error: conflicting types for 'printstring'
void printstring(int n, int m, char (*w)[m]){
^~~~~~~~~~~
test.c:5:6: note: previous declaration of 'printstring' was here
void printstring(int, int,char **);
^~~~~~~~~~~
the problem is that you're using a variable length array. The last argument (the list of strings) depends on the second argument (m). And char ** is not suitable, as it's just a pointer on pointers. So the max dimension of the strings would be lost when iterating on the 2D array.
Use a standard forward declaration, copying exactly the real declaration if you don't want to put the function before the main one.
void printstring(int n, int m, char (*w)[m]);
int main(){
char word[3][6]= {"hello","world","I"};
printstring(3,6,word);
return 0;
}
void printstring(int n, int m, char (*w)[m]){
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
If you have read-only strings, I suggest that you use a standard array of constant pointers instead:
void printstring(int n, const char *w[]);
int main(){
const char *word[] = {"hello","world","I"};
printstring(3,word);
return 0;
}
void printstring(int n, const char *w[])
{
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
note that
printstring(3,word);
can be replaced by
printstring(sizeof(word)/sizeof(word[0]),word);
before array decays to pointer (that autocomputes the number of strings)
If you want to maintain a name free declaration for whatever reason, you can use the * notation (reserved to function prototype scope) for the variably modified type
void printstring(int, int,char (*)[*]);
Still a VLA, and in fact, exactly equivalent to the notation that uses m. Though, ostensibly, it may convey intent not as clearly as using m in the forward declaration.
The following should just work:
void printstring(int n, int m, char (*w)[m]);
The function prototype and definition should be kept identical, except maybe for certain qualifiers such as const and default arguments in C++.
char** cannot be used to point at 2D arrays, it can only be used to point at the first element of a 1D array of char*, which is something else.
Your compiler error is from having non-matching declaration and definition. Correct code:
void printstring(int n, int m, char w[n][m]);
...
void printstring(int n, int m, char w[n][m]){
...
}
Alternatively, you can write void printstring(int n, int m, char (*w)[m]) and it is completely equivalent. But that is just harder to read, so why would you?

Invalid type of arguments C

I am trying to implement a function that read lines from a file and put them into a string array. But it gives me the warning:
expected char ** But argument is of type char * (*)[(sizetype)(numberOfchar)]
It was working on Windows but when I switch into Linux it stops working.
Here is the caller and the array variable :
char *hashes[numberOfchar];
PutInArray(textName, numberOfchar, &hashes);
And here is the function (the void* is for the next part of the program, threading) :
void* PutInArray(char* k, int d, char *tab[d]) {
FILE* fp = NULL;
int i;
fp = fopen(k, "r");
if(fp != NULL) {
for (i = 0; i < d; i++) {
tab[i] = (char *)malloc((34) * sizeof(char));
fgets(tab[i], 34, fp);
}
fclose(fp);
}
}
Let's see how function calls work for other types.
You have a variable int v; and a function void foo(int x) (the variable declaration and the parameter declaration look the same). You call foo(v). You also have a function void bar(int* x) (the variable declaration has one star less than the parameter declaration). You call bar(&v).
You have a variable int* v; and a function void foo(int* x) (the variable declaration and the parameter declaration look the same). You call foo(v). You also have a function void bar(int** x) (the variable declaration has one star less than the parameter declaration). You call bar(&v).
You have a variable const struct moo ***v and a function void foo(const struct moo ***x) (the variable declaration and the parameter declaration look the same). You call foo(v). You also have a function void bar(const struct moo ****x) (the variable declaration has one star less than the parameter declaration). You call bar(&v).
You have a variable char *hashes[numberOfchar] and a function void* PutInArray(char* k, int d, char *tab[d]). The variable declaration and the parameter declaration still look the same. Why on God's green earth stick & in front of the variable?
I hear you saying "but I want to pass hashes by reference, and to pass by reference I need to use &". Nope, arrays are automatically passed by reference (or rather an array automatically gets converted to a pointer of its first element; parameters of array type are similarly adjusted so that the rule formulated above just works).
For completeness, the analogue of bar would have a parameter that looks like this:
char* (*tab)[numberOfchar]
and if you had such parameter, you would have to use &hashes. But you don't need it.
Your code is almost OK. Concerning the error/warning you get, just write PutInArray(textName, numberOfchar, hashes) instead of PutInArray(textName, numberOfchar, &hashes) for the following reason:
In function PutInArray(char* k, int d, char *tab[d]), char *tab[d] has the same meaning as char*[] and char**, i.e. it behaves as a pointer to a pointer to a char.
Then you define hashes as char *hashes[numberOfchar], which is an array of pointers to char. When using hashes as function argument, hashes decays to a pointer to the first entry of the array, i.e. to a value of type char **, which matches the type of argument tab. However, if you pass &hashes, then you'd pass a pointer to type char *[], which is one indirection to much. (BTW: passing &hashes[0] would be OK).
BTW: PutInChar should either return a value or should be declared as void PutInArray(char* k, int d, char *tab[d]) (not void*).

What does "[*]" (star modifier) mean in C? [duplicate]

This question already has answers here:
Why use an asterisk "[*]" instead of an integer for a VLA array parameter of a function?
(2 answers)
Closed 6 years ago.
While trying to implement a C11 parser (for educational purposes), I found that in C11 (p. 470) but also in C99 (p. 412) (thanks Johannes!), the direct declarator is defined as:
(6.7.6) direct-declarator:
direct-declarator [ type-qualifier-list? * ]
At first, I thought this was an error in the grammar (the type list shouldn't be optional). However, when I tried this out in my reference compiler (clang), I got an rather unexpected error:
int array[*] = { 1, 2, 3 };
// error: star modifier used outside of function prototype
So apparently, (in clang) this is called the star modifier.
I quickly learned that they can only be used in function signatures:
void foobar(int array[*])
However, they can only be used in the declaration. Trying to use it in a function definition results in an error as well:
void foobar(int array[*]) {
// variable length array must be bound in function definition
}
So as far as I can tell, the intended behaviour is to use [*] in the function declaration and then use a fixed number in the function definition.
// public header
void foobar(int array[*]);
// private implementation
void foobar(int array[5]) {
}
However, I have never seen it and I don't quite understand the purpose of it either.
What is its purpose, why was it added?
What's the difference with int[]?
What's the difference with int *?
What is its purpose, why was it added?
Purpose is seen when a variable length two dimentional array is used as a function parameter. The function
int foo(int n, int m, int a[n][m]) {...}
can be prototyped as any of the following
int foo(int , int, int [][*]);
int foo(int , int, int a[*][*]);
int foo(int , int, int (*a)[*]);
int foo(int n, int, int a[n][*]);
int foo(int , int m, int a[*][m]);
int foo(int , int m, int (*a)[m]);
int foo(int n, int m, int a[n][m]);
In case of two dimensional array, when used as function parameter, size of the second dimension can't be omitted. If the name of first variables in function prototype is omitted then it wouldn't be possible to specify the length (second dimension) of the array. The * gives the clue that the length of the array will be determined by the second parameter.
What's the difference with int[]?
What's the difference with int *?
In case of 1D array, for the function definition
int bar(int n, int a[n]} {...}
any of the following prototype is valid
int bar (int , int *);
int bar (int , int [*]);
int bar (int , int []);
int bar (int n, int a[]);
int bar (int n, int a[n]);
int bar (int n, int [n]);
In this case neither * nor n is necessary as compiler will treat both of int [*] and int [n] as int *. So, with one dimensional array you can't see much difference.
NOTE: When using variable length array as a function parameter, order of parameter is important. Order of parameters for first four prototypes of bar can be switched, but in latter two first parameter must not be the array itself.
int bar (int a[n], int n); //Wrong. Compiler has not yet seen 'n'.
The C rationale document for C99 says
A function prototype can have parameters that have variable length array types (§6.7.5.2) using a special syntax as in
int minimum(int, int [*][*]);
This is consistent with other C prototypes where the name of the parameter need not be specified.
What's the difference with int[]
What's the difference with int *.
I think it's simply that those types in a function prototype means "pointer", while a [*] in a non-top position (int[*] still equals int[] I think, in a function prototype) actually is valid and means array
// not recommended though: it is now unclear what the parameters
// mean to human callers!
void f(int, int [][*]);
void f(int n, int x[][n]) {
x[1][0] = 1;
}
int main() {
int a[2][1];
f(1, a);
printf("%d\n", a[1][0]);
}
As for the purpose, when indexing the array in the function definition, the compiler needs to know how many integers of the next index to skip when giving the first index (x[i] skips i * n integers in f above). But this information is not needed in the non-defining prototype declaration, hence it can be left out and replaced by *.

Passing 2D array of structs

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.

How to pass an array of struct using pointer in c/c++?

in C code I'm stuck to pass an array of struct to a function, here's the code that resembles my problem:
typedef struct
{
int x;
int y;
char *str1;
char *str2;
}Struct1;
void processFromStruct1(Struct1 *content[]);
int main()
{
Struct1 mydata[]=
{ {1,1,"black","cat"},
{4,5,"red","bird"},
{6,7,"brown","fox"},
};
processFromStruct1(mydata);//how?!?? can't find correct syntax
return 0;
}
void processFromStruct1(Struct1 *content[])
{
printf("%s", content[1]->str1);// if I want to print 'red', is this right?
...
}
Compile error in msvc is something like this:
error C2664: 'processFromStruct1' : cannot convert parameter 1 from 'Struct1 [3]' to 'Struct1 *[]'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
How to solve this? tnx.
You almost had it, either this
void processFromStruct1(Struct1 *content);
or this
void processFromStruct1(Struct1 content[]);
and, as Alok points out in comments, change this
content[1]->str1
to this
content[1].str1
Your array is an array of structures, not an array of pointers, so once you select a particular structure with [1] there is no need to further dereference it.
Try
processFromStruct1( & mydata[ i ] ); // pass the address of i-th element of mydata array
and the method to
void processFromStruct1(Struct1 *content )
{
printf("%s", content->str1);
...
}
(2nd part already noted by John Knoeller and Alok).
John Knoeller gave the perfect syntax , I am trying to explain some basic things,
I hope that it willsolve your confusions in future.
This is very similar to passing pointer to a function in C.
Of course struct is also a pointer,
so we can pass the value in 2 ways
0. Via pointer
0. Via array ( since we are using array of struct )
so the problem is simple now ,
You have to give the data type of a variable as we do in normal pointers ,
here the data type is user-defined ( that means struct ) Struct1 then variable name,
that variable name can be pointer or array name ( choose a compatible way ).
This works for me. Changed structs to C++ style.
struct Struct1
{
int x;
int y;
char *str1;
char *str2;
};
Struct1 mydata[]=
{ {1,1,"black","cat"},
{4,5,"red","bird"},
{6,7,"brown","fox"},
};
void processFromStruct1(Struct1 content[]);
int main()
{
processFromStruct1(&mydata[1]);
return 0;
}
void processFromStruct1(Struct1 content[])
{
printf("%s",content->str1);
}
output: red
Perhaps a proper re-factoring from the future:
#include <stdio.h>
typedef struct
{
int x;
int y;
char *str1;
char *str2;
} struct_1;
static void proc_the_struct_1_arr (
const int count_ ,
// array arg declared with min number of arguments
// also can not be null
struct_1 content[ static count_ ]
)
{
for (unsigned j = 0; j < count_; ++j)
printf("x:%-4dy:%-4d%-12s%-12s\n", content[j].x,content[j].y,content[j].str1,content[j].str2);
}
int main( void )
{
struct_1 mydata[3]= {
{.str1 = "black", .str2 = "cat" },
{.str1 = "red", .str2 = "bird"},
{.str1 = "brown", .str2 = "fox" },
};
proc_the_struct_1_arr (3,mydata);
return 0;
}
Godbolt
Obviously proc_the_struct_1_arr declaration is interesting. That actually uses Variably Modified Types (VMT). That is a legal syntax only for array arguments.
That is not slower vs the pointer to array solution:
static void proc_the_struct_1_arr_pointer (
const int count_ ,
// array arg not declared with min
// required number of arguments
struct_1 (*arr_ptr)[ /* static no allowed here */ count_ ]
);
I assume the compiler "rewrites" the above to the array pointer, anyway. On the second option arr_ptr can be a null argument.
You can try the prototype as void processFromStruct1(Struct1 content[]); and then the declaration should be like void processFromStruct1(Struct1 content[]).

Resources