passing pointers to nested functions - c

I am having problems passing a pointer to a pointer(struct) through a nested function to have memory allocated or reallocated for it. I understand that when passing to a function it is passed by value, and thus only can be edited locally, but am unclear syntactically how to pass it. Important code snippets below:
struct courseData{
char name[25];
int id;
};
void menuSwitch(int* courseNum, struct courseData** course);
void addCourse(int* courseNum, struct courseData** course);
int main(){
struct courseData* course = NULL;
int courseNum = 0;
menuSwitch(courseNum, &course); //Edited from original post.
return 0;
}
void menuSwitch(int* courseNum, struct courseData** course){
addCourse(&courseNum, course)
}
menuSwitch is actually a case switch, which calls function addCourse when the menu item is selected.
void addCourse(int* courseNum, struct courseData** course){
if(*courseNum == 0)
*course = (struct courseData*) malloc(sizeof(struct courseData));
else
*course = (struct courseData*) realloc(*course, (*courseNum + 1)*sizeof(struct courseData));
*courseNum = *courseNum + 1; //Increments course count by 1
------code continues------
}
After correcting original problem, compiling results in the following errors/warnings from gcc
main.c: In function ‘main’:
main.c:27:3: warning: passing argument 2 of ‘menuSwitch’ from incompatible pointer type [enabled by default]
header.h:24:6: note: expected ‘struct courseData *’ but argument is of type ‘struct courseData **’
func.c:60:6: error: conflicting types for ‘menuSwitch’
header.h:24:6: note: previous declaration of ‘menuSwitch’ was here
func.c: In function ‘menuSwitch’:
func.c:64:3: warning: passing argument 2 of ‘addCourse’ from incompatible pointer type [enabled by default]
header.h:26:6: note: expected ‘struct courseData *’ but argument is of type ‘struct courseData **’
Thank you for your help, and pardon if this is inappropriate use of the edit ability.

Everything is fine except one line. In void menuSwitch(int* courseNum, struct courseData** course) change
addCourse(&courseNum, course)
to
addCourse(courseNum, course);

You were doing fine until you got to menuSwitch. That function receives courseNum, which is a pointer to int. It should then pass that same pointer addCourse just as it does with course. However, you pass the address of courseNum instead. So instead of passing an int * you're passing the address of a pointer to int *, or an int **. The call to addCourse should simply be this:
addCourse(courseNum, course);

Related

Getting an error in C: passing argument 1 of function from incompatible pointer type

The function signature is
void abort(context_t **ctx);
, where ctx is a property of another struct.
After I have created a pointer to the main struct ( server_t *server ), I can pass the pointer to the pointer to the main struct ( **server ) around with no problem, using the pointers to its properties like this: (*server)->ctx or (*server)->addr, etc.
But I cannot figure out how to pass the **ctx to a function directly, without passing the **server. If I try it as abort(&server->ctx), I get an error:
error: passing argument 1 of ‘abort’ from incompatible pointer type: abort(&server->ctx);
note: expected ‘context_t ** {aka struct context_t **}’ but argument is of type ‘struct context_t *’
void abort(context_t **ctx);
note: expected ‘context_t ** {aka struct context_t **}’ but argument is of type ‘struct context_t *’
It seems you try to assign pointer to double pointer. You can try:
context_t * temp_ctx = &server->ctx;
abort(&temp_ctx);
The compiler error can be fixed by the following lines of codes:
/* declare context_t* pointer variable on the appropriate scope */
/* based on how **ctx is used by abort() */
context_t *pContext;
/* .... */
/* assign the pointer */
pContext = &server->ctx;
/* now pass the context_t** or "the address of pContext" to abort() */
abort(&pContext);

pointer confusion - error: passing argument 1 of ‘value’ from incompatible pointer type; note: expected ‘...’ but argument is of type ‘...'

EDIT: This was so obvious, I have no idea how I didn't notice. Thanks for your help, guys!
I am making a symbol table using binary tree in C, and I got stuck while defining the basic functions. I have never been able to fully grasp pointer operations, and these errors are making my head hurt and I have no idea how to fix them, although I'm sure that many of you will find my problem trivial.
I have a structure defined like this:
typedef struct SymTable {
symbol_t *rootNode;
} symTable_t;
An initialisation function like this:
void initTable(symTable_t *table) {
table->rootNode = NULL;
}
And in my main.c I call the function:
symTable_t *newTable = malloc(sizeof(symTable_t));
// check if malloc was successful
initTable(&newTable);
It throws these two errors when I try to translate:
main.c:12:12: error: passing argument 1 of ‘initTable’
from incompatible pointer type [-Werror=incompatible-pointer-types]
initTable(&newTable);
^
In file included from main.c:1:0:
sym_tab.c:18:7: note: expected ‘symTable_t * {aka struct SymTable *}’ but argument is of type ‘symTable_t ** {aka struct SymTable **}’
void initTable(symTable_t *table) {
When I define initTable() like _initTable(symTable_t table)_, it only throws more errors.
Thank you in advance.
You're passing a pointer to a pointer to a symTable_t instead of just a pointer to a symTable_t.
Remove the & in this line:
initTable(&newTable);
and the error will go away.

c warning - passing argument 1 of ‘insert’ from incompatible pointer type [duplicate]

This question already has an answer here:
Passing argument from incompatible pointer type warning
(1 answer)
Closed 6 years ago.
I'm a newbie to C programming. I have to write some functions/procedures for homework, and then test them with a make test given by the professor.
I have a struct with two element: the first element is a pointer to a list and the second element is the type of order according to which the list is sorted. Here are the data struct:
/* order type
NOTORD = no order
TIME = ordered by increasing time
POSITION = ordered by increasing position */
typedef enum {NOTORD=0, TIME=1, POSITION=2} ord_t;
typedef struct elem {
double position;
double time;
struct elem * next;
} elem_t;
typedef struct {
elem_t * head;
ord_t ord;
} lista_t;
I have to insert an element (given by input) to the list, according to the type of order. Here is my code:
void inserisciInTesta(lista_t *l, elem_t *el) {
el->next=l->head;
l->head=el;
}
void inserisciTime(lista_t * l, elem_t* pelem) {
if(l->head->time >= pelem->time)
inserisciInTesta(l, pelem);
else
inserisciTime(l->head->next, pelem);
}
void inserisciPosition(lista_t * l, elem_t* pelem) {
if((l->head)->position >= pelem->position)
inserisciInTesta(l, pelem);
else
inserisciPosition(l->head->next, pelem);
}
int inserisci(lista_t * l , elem_t* pelem) {
if(l->ord==TIME) {
inserisciTime(l, pelem);
return 0;
}
else if(l->ord==POSITION){
inserisciPosition(l, pelem);
return 0;
}
else {
inserisciInTesta(l, pelem);
return 0;
}
}
Making the test, I get these warnings:
raggi.c: In function ‘inserisciTime’:
raggi.c:42:27: warning: passing argument 1 of ‘inserisciTime’ from incompatible pointer type [-Wincompatible-pointer-types]
inserisciTime(l->head->next, pelem);
^
raggi.c:38:6: note: expected ‘lista_t * {aka struct *}’ but argument is of type ‘struct elem *’
void inserisciTime(lista_t * l, elem_t* pelem) {
^
raggi.c: In function ‘inserisciPosition’:
raggi.c:49:31: warning: passing argument 1 of ‘inserisciPosition’ from incompatible pointer type [-Wincompatible-pointer-types]
inserisciPosition(l->head->next, pelem);
^
raggi.c:45:6: note: expected ‘lista_t * {aka struct *}’ but argument is of type ‘struct elem *’
void inserisciPosition(lista_t * l, elem_t* pelem) {
^
What is wrong with my code? Thanks in advance for helping.
The compiler warnings pretty much say it all. Consider the first one. insetisciTime expects a lista_t * as its first argument. The bad call is passing l->head->next. What type is that? Well, l is a lista_t *. So l->head is an elem_t *. So l->head->next is a struct elem *, which is equivalent to elem_t *. That's a type mismatch: The function expects a lista_t *, and you're passing an elem_t *.
One of the two has to change: Either change the function to match what you're passing, or change what you're passing to match what the function expects. The compiler warning is saving you here, since there's no way it could possibly work as is.
The other warning has the exact same problem.
The cause of the error is what Tom explains. I'd recommend that you change the functions and instead of using a recursive call (i.e. the function calls itself) you use a while loop to find where you need to insert the element.
Take into account that you need to modify two pointers when you insert a new element: the pointer to the next element, and the pointer from the previous one. Doing this with a recursive function may be more confusing.
Also, check for the special cases of inserting at the beginning of the list, at the end of the list, and if the list is empty.

Strange pointer warning while printing directory listing

I have the following code to print the directory listing in unix.
struct dirent *res;
struct DIR *dir;
scanf("%s",str);
dir=opendir(str);
if(dir==NULL)
{
perror("Invalid directory");
return 1;
}
res=(struct dirent *)readdir(dir);
while(res)
{
printf("%s\n",res->d_name);
res=(struct dirent *)readdir(dir);
}
When I compile the above code I get the following warning
ls.c:16:17: warning: passing argument 1 of ‘readdir’ from incompatible pointer type
[enabled by default]
/usr/include/dirent.h:164:23: note: expected ‘struct DIR *’ but argument is of type
‘struct DIR *’
ls.c:20:21: warning: passing argument 1 of ‘readdir’ from incompatible pointer type
[enabled by default]
/usr/include/dirent.h:164:23: note: expected ‘struct DIR *’ but argument is of type
‘struct DIR *’
What does GCC exactly mean when it says "Expected argument foo but argument is of type foo"?
I also tried using struct DIR dir instead of *dir and &dir instead of dir,but it results in following error
ls.c:7:12: error: storage size of ‘dir’ isn’t known
PS:The output of the code is perfectly OK.
DIR is a macro which generally expands to struct something, so you're declaring struct struct something *dir. Which is apparently a confusing thing to do (though, also apparently, fine by GCC), leading to a confusing error message. The solution is simply to declare DIR *dir, without the struct.
Ben has the correct solution to your problem, but this does look like a serious problem in how gcc reports this error.
First of all, it wasn't a macro issue. DIR is a typedef for struct __DIR (at least that's what it is here, and I get the same error message). There is no struct DIR except the one declared by struct DIR *dir; but gcc seems to be saying there is another type with that name.
This sample compilation unit demonstrates the problem more clearly:
struct foo {
int a,b,c;
};
typedef struct foo bar;
void do_bar(bar *);
void func(void)
{
int i = 0;
/* do_bar wants a bar *, which is a struct foo *, but we're giving it an
int * instead. What will gcc say? */
do_bar(&i);
}
gcc reports:
t.c: In function ‘func’:
t.c:15:7: warning: passing argument 1 of ‘do_bar’ from incompatible pointer type [enabled by default]
t.c:7:10: note: expected ‘struct bar *’ but argument is of type ‘int *’
but there is no struct bar in the code at all. It has taken the bar typedef and crammed the word struct in front of it for no reason.

passing an argument ( a struct in an array of structs within a struct) to a function in C

I have a struct "course" and a function for it:
typedef struct Course_s
{
char* name;
int grade;
} Course;
int courseGetGrade(Course const* course)
{
assert(course);
return course -> grade;
}
and another struct "transcript" and a function:
typedef struct Transcript_s
{
char* name;
struct Course** courseArray;
} Transcript;
double tsAverageGrade(Transcript const *t)
{
double temp = 0;
int a = 0;
while(t -> courseArray[a] != NULL)
{
temp = temp + courseGetGrade(t -> courseArray[a]);
a++;
}
return (temp / a);
}
But I cannot seem to pass the argument t -> courseArray[a] to the function courseGetGrade. I'm a little confused with pointers and how this should be implemented, I just don't see why it doesn't work the way it is. The courseArray is an array of Course structs, with a NULL pointer at the end of the array.
I get a warning "passing argument 1 of "courseGetGrade" from incompatible pointer type". If I try adding "const" before the argument the warning changes to an error: expected expression before "const".
I'm using plain C.
All help is much appreciated!
Edit. Here is the full compiler output. There are more functions and therefore more warnings in the full output than in the code I originally posted:
transcript.c: In function âtsAverageGradeâ:
transcript.c:66: warning: passing argument 1 of âcourseGetGradeâ from incompatible pointer type
course.h:27: note: expected âconst struct Course *â but argument is of type âstruct Course *â
transcript.c: In function âtsSetCourseArrayâ:
transcript.c:89: error: invalid application of âsizeofâ to incomplete type âstruct Courseâ
transcript.c:94: warning: assignment from incompatible pointer type
transcript.c: In function âtsPrintâ:
transcript.c:114: warning: passing argument 1 of âcourseGetNameâ from incompatible pointer type
course.h:24: note: expected âconst struct Course *â but argument is of type âstruct Course *â
transcript.c:114: warning: passing argument 1 of âcourseGetGradeâ from incompatible pointer type
course.h:27: note: expected âconst struct Course *â but argument is of type âstruct Course *â
transcript.c: In function âtsCopyâ:
transcript.c:126: warning: passing argument 2 of âtsSetCourseArrayâ from incompatible pointer type
transcript.c:80: note: expected âstruct Course **â but argument is of type âstruct Course ** constâ
Edit.2 Here is the function causing the error in line 89:
void tsSetCourseArray(Transcrpt *t, Course **courses)
{
assert(t && courses);
free(t -> courseArray);
int a = 0;
while(courses[a] != NULL)
a++;
t -> courseArray = malloc(sizeof(struct Course) * (a+1));
a = 0;
while(courses[a] != NULL)
{
t -> courseArray[a] = courseConstruct(courseGetName(courses[a]), courseGetGrade(courses[a]));
a++;
}
t -> courseArray[a] = NULL;
}
Change:
typedef struct Transcript_s
{
char* name;
struct Course** courseArray;
} Transcript;
to:
typedef struct Transcript_s
{
char* name;
Course** courseArray; /* 'Course' is a typedef for 'struct Course_s'. */
} Transcript;
Also the following is incorrect, for two reasons:
t -> courseArray = malloc(sizeof(struct Course) * (a+1));
struct Course should be Course but more importantly it should be Course* as space needs to be allocated for the Course*: t->courseArray is a Course**. Change to:
t -> courseArray = malloc(sizeof(Course*) * (a+1));
Also, the following will not free the Course instances in the courseArray, it will only free the array of pointers:
free(t -> courseArray);
You need to iterate over courseArray and free each individual element and then free the array of pointers:
while (t->courseArray[a] != NULL)
{
free(t->courseArray[a]->name); /* If name was dynamically allocated. */
free(t->courseArray[a]);
}
free(t -> courseArray);

Resources