Error when passing struct to function in c - c

When I pass a struct to a function, I get the error: expected ‘struct book’ but argument is of type ‘struct book'. Why is this happening?
#include <stdio.h>
#include <string.h>
struct book
{
int id;
char title[50];
};
int showBooks(struct book x);
int main()
{
struct book
{
int id;
char title[50];
};
struct book book1,book2;
book1.id = 2;
book2.id = 3;
strcpy(book1.title, "c programming");
strcpy(book2.title, "libc refrence");
printf("Book\t\tID\n");
showBooks(book1);
showBooks(book2);
}
int showBooks(struct book x)
{
printf("%s\t%d\n", x.title, x.id);
}
The error:
30:12: error: incompatible type for argument 1 of ‘showBooks’
showBooks(book1);
10:5: note: expected ‘struct book’ but argument is of type ‘struct
book’ int showBooks(struct book x);
31:12: error: incompatible type for argument 1 of ‘showBooks’
showBooks(book2);
10:5: note: expected ‘struct book’ but argument is of type ‘struct
book’ int showBooks(struct book x);
where the error here?

Your two different struct definitions define two different types. Even though they are both called struct book, they are not the same type.
Your variables book1 and book2 have a type of the local struct, but the function expects a struct of the type of the global struct, hence the error.
You could fix the problem by deleting the local struct definition; then book1 will have the type of the global struct etc.

A local variable or parameter that hides a global variable of the same name. This may be confusing. The "struct book" inside the main() hides the global definition of the "struct book".
The variables book1 and book2 are the type of "struct book" with local reference to the main().
The showBooks() use arguments as the book1 or book2 as formal parameters.
The actual parameter uses the global definition of the "struct book" which results in incompatible type.
Comment the local definition and find the difference.

Related

Unable to Print the Content of a Structure

I want to print the content of the book record as defined in the print_book() function. Here is the code. My intention is to use the function to print any struct of type Book.
#include <stdio.h>
#include <string.h>
void print_book(struct Book book);
struct Book
{
int id;
char *title;
char *author;
int pages;
};
int main(void)
{
struct Book book_1;
book_1.id = 23;
strcpy(book_1.title, "Java! A Complete Reference");
strcpy(book_1.author, "Ryna Dahl");
book_1.pages = 876;
print_book(book_1);
return 0;
}
void print_book(struct Book book)
{
printf("BOOK\n");
printf("Book ID: %i\n", book.id);
printf("Book Ttitle: %s\n", book.title);
printf("Book Author: %s\n", book.author);
printf("Number of Pages: %i\n", book.pages);
}
Here is the error I am receiving in the console
muyiwa#muyiwa-HP-Pro-3010-Microtower-PC:~/Documents/C$ clang -o struct_pointer struct_pointer.c
struct_pointer.c:4:24: warning: declaration of 'struct Book' will not be visible outside of this function [-Wvisibility]
void print_book(struct Book book);
^
struct_pointer.c:22:16: error: argument type 'struct Book' is incomplete
print_book(book_1);
^~~~~~
struct_pointer.c:4:24: note: forward declaration of 'struct Book'
void print_book(struct Book book);
^
struct_pointer.c:26:6: error: conflicting types for 'print_book'
void print_book(struct Book book)
^
struct_pointer.c:4:6: note: previous declaration is here
void print_book(struct Book book);
^
1 warning and 2 errors generated.
muyiwa#muyiwa-HP-Pro-3010-Microtower-PC:~/Documents/C$ clang -o struct_pointer struct_pointer.c
struct_pointer.c:4:24: warning: declaration of 'struct Book' will not be visible outside of this function [-Wvisibility]
void print_book(struct Book book);
^
struct_pointer.c:16:17: error: variable has incomplete type 'struct Book'
struct Book book_1;
^
struct_pointer.c:16:12: note: forward declaration of 'struct Book'
struct Book book_1;
^
struct_pointer.c:26:24: warning: declaration of 'struct Book' will not be visible outside of this function [-Wvisibility]
void print_book(struct Book book)
^
struct_pointer.c:26:6: error: conflicting types for 'print_book'
void print_book(struct Book book)
^
struct_pointer.c:4:6: note: previous declaration is here
void print_book(struct Book book);
^
struct_pointer.c:26:29: error: variable has incomplete type 'struct Book'
void print_book(struct Book book)
^
struct_pointer.c:26:24: note: forward declaration of 'struct Book'
void print_book(struct Book book)
^
2 warnings and 3 errors generated.
I have tried all possible means, and on checking other sources, my code looks correct.
Scopes of Declarations
When something is newly declared in a function parameter, its scope (the portion of source code in which it is visible) is limited to the function declaration. So, in void print_book(struct Book book);, struct Book declares a type that is known only inside that declaration. When the definition of struct Book appears later, it is a different struct Book.
If you put the definition of struct Book first, outside of any function, then its scope is the rest of the translation unit (the file being compiled along with any files it includes with #include). Then, when void print_book(struct Book book);appears later, thisstruct Book` will not define a new type; it will refer to the type that is already in scope.
Lesson: Never make struct Name inside a parameter declaration the first appearance of struct Name in the code.
Note that you do not need to fully define the structure first. Merely putting a struct Book; first would inform the compiler there is a type struct Book with file scope. You could put the definition later (but before the compiler needs to know about the members of the structure).
Allocation of Memory
In this code:
strcpy(book_1.title, "Java! A Complete Reference");
strcpy(book_1.author, "Ryna Dahl");
no memory has yet been allocated for book_1.title or book_1.author. These members are merely pointers that have not been given a value. To use strcpy correctly, you must allocate memory for the strings and set the pointers to point to that memory.
You can just set the pointers to point to the string literals directly:
book_1.title = "Java! A Complete Reference";
book_1.author = "Ryna Dahl";
That sets the members to point to strings that you should treat as constants. If you want to have modifiable memory, you could do this:
// Make temporary pointers to the string literals.
char *Title = "Java! A Complete Reference";
char *Author = "Ryna Dahl";
// Allocate memory for copies, including the terminating null characters.
book_1.title = malloc(strlen(Title) + 1);
book_1.author = malloc(strlen(Author) + 1);
if (!book_1.title || !book_1.author)
{
fprintf(stderr, "Error, unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
// Copy the strings into the allocated memory.
strcpy(book_1.title, Title);
strcpy(book_1.author, Author);
Generally, if you allocate memory in this way, you should call free to release it when you are done using it. (In general-purpose multiuser operating systems, this can be omitted when the program is terminating, as the operating system will reclaim all memory.)
#include <stdio.h>
#include <string.h>
#define TITLE_SIZE (128)
#define AUTHOR_SIZE (128)
struct Book
{
int id;
int pages;
char title[TITLE_SIZE];
char author[AUTHOR_SIZE];
};
void print_book(struct Book book);
int main(void)
{
struct Book book_1;
book_1.id = 23;
strcpy(book_1.title, "Java! A Complete Reference");
strcpy(book_1.author, "Ryna Dahl");
book_1.pages = 876;
print_book(book_1);
return 0;
}
void print_book(struct Book book)
{
printf("BOOK\n");
printf("Book ID: %i\n", book.id);
printf("Book Ttitle: %s\n", book.title);
printf("Book Author: %s\n", book.author);
printf("Number of Pages: %i\n", book.pages);
}

Passing struct to a function to assign values

I am trying to pass a struct to a function residing in a separate file. When passing the struct as an argument, it throws errors.
Test.c
struct student{
int rollNumber;
unsigned char name[20];
int marks;
};
void func(struct student devanshu);
int main(){
struct student devanshu;
func(&devanshu);
printf("--------------------%d\n", devanshu.rollNumber);
printf("--------------------%d\n", devanshu.marks);
printf("--------------------%s\n", devanshu.name);
}
NewTest.c:
void func(struct student devanshu)
{
devanshu.rollNumber = 1;
devanshu.marks = 909;
strcpy(devanshu.name, "abc.xyz");
return;
}
And this is the output that I get:
In file included from test.c:6:0:
newtest.c:10:30: error: parameter 1 (‘devanshu’) has incomplete type
void func(struct student devanshu)
test.c: In function ‘main’:
test.c:23:7: error: incompatible type for argument 1 of ‘func’
func(&devanshu);
^
In file included from test.c:6:0:
newtest.c:10:6: note: expected ‘struct student’ but argument is of type ‘struct student *’
void func(struct student devanshu)
newtest.c:10:30: error: parameter 1 (‘devanshu’) has incomplete type
void func(struct student devanshu)
newtest.c:7:20: error: storage size of ‘devanshu’ isn’t known
struct student devanshu;
If I use the function in the same file i.e in test.c it does not throw any error and works just fine. But when keeping the functions in two different files, it gives me these errors.
Would be thankful if somebody could help me get through. Thanks in advance.
error: parameter 1 (‘devanshu’) has incomplete type
This means that the struct definition isn't visible to the file you use it inside. Unless this is intentional, you need to place the struct definition in a header file and include that by every .c file using the struct.
expected ‘struct student’ but argument is of type ‘struct student *’
You have written the functions incorrectly. It should be void func(struct student* devanshu); and inside the function you should access members with devanshu-> .... Otherwise you just pass a copy of the struct to the function and then change the local copy.
The errors are pretty self explanatory. Take this one:
test.c: In function ‘main’:
test.c:23:7: error: incompatible type for argument 1 of ‘func’
func(&devanshu);
It means you're passing something to func that has a different type to what you've told the compiler that func accepts. You've declared the function to take a struct student
void func(struct student devanshu);
but the function call is passing a pointer to struct student.
func(&devanshu);
The function call is correct as you want the function to have access to the struct you're passing and not a copy. So you'll need to change the function to take a struct student *.
The other errors are because you're not using an include file to store the definition of the struct.
Create a file called "student.h" (or whatever) and move the definition of the struct into it. And also the declaration of the function too.
struct student{
int rollNumber;
unsigned char name[20];
int marks;
};
void func(struct student *);
and at the top of both C files you put
#include "student.h"
which tells the compiler to copy the contents of that file into your C files when you're compiling. It means you have a consistent definition that can be shared by all the files that need it.
Ok, this will work: (Explanation below)
test.h: (New file!)
struct student{
int rollNumber;
char name[20];
int marks;
};
test.c:
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
void func(struct student *devanshu);
int main(){
struct student devanshu;
func(&devanshu);
printf("--------------------%d\n", devanshu.rollNumber);
printf("--------------------%d\n", devanshu.marks);
printf("--------------------%s\n", devanshu.name);
}
NewTest.c:
#include <string.h>
#include "test.h"
void func(struct student *devanshu)
{
devanshu->rollNumber = 1;
devanshu->marks = 909;
strcpy(devanshu->name, "abc.xyz");
return;
}
This
unsigned char name[20];
will give you problems later on strcpy(). Change to just char.
This
void func(struct student devanshu);
is not wrong, but you fall into a trap. Structures in C are always passed by value (copy) of the entire struct. So, if you want func() to modify the original struct, you have to explicitly tell it so:
void func(struct student *devanshu);
Then, in func, you need to change the access syntax to using the -> operater insteadf of '.'
As you are using the struct student in both files, you need to move the declaration of the struct out into a header file. You could (as I did on the very first edit) also repeat the declaration because I was lazy, but the comments are 100% right: That is a very dangerous practice, so I changed that.

How to properly allocate memory for structs, arrays of structs inside a struct, and passing that array as a parameter

I've been quite aways away from C and as I am diving back into it I have found myself hitting a roadblock. I have the following structure:
typedef struct{
char id;
struct S *children[SIZE];
}S;
In my code I initially declare an array of structs...
struct S arr[SIZE];
But when I get to this point of trying to allocate my first child for my first member of arr...
arr[0].children[0] = (S*)malloc(sizeof(S));
I get this warning: warning: incompatible implicit declaration of built-in function ‘malloc’ warning: assignment from incompatible pointer type [enabled by default]
On top of this I'm getting an error that doesn't sound very logical to me. I have the following function:
int foo(S *children[SIZE]);
but when I call this line....
foo(arr[0].children);
I get this note: note: expected ‘struct S **’ but argument is of type ‘struct S **’
which to me just sounds silly, it is expecting the argument it is getting and is upset about it.
Any help in explaining what I should be doing to properly allocate this memory and achieve the same idea would be very much appreciated.
There is no struct S, only S which is a typedef of anonymous structure.
Define struct S too:
typedef struct S {
char id;
struct S *children[SIZE];
}S;
Or:
typedef struct S S;
struct S {
char id;
S *children[SIZE];
};
And do avoid casting return of malloc in C:
arr[0].children[0] = malloc(sizeof(S));
For your first problem, you need to do:
#include <stdlib.h>
at the top of your program, in order to call malloc successfully.
The second problem (as also pointed out by others) is that struct S in your class definition refers to a different struct than S. In C, struct tags are in a different "namespace" than type names.

passing pointers to nested functions

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

Incompatible types when assigning to type ‘typedef from type ‘uint8_t’

I am running across a problem with typedefs.
typedef char cool_array_t[ARRAY_SIZE];
cool_array_t* out;
// do stuff with out
cool_array_t test = *out;
The error I am getting is the following:
incompatible types when assigning to type ‘cool_array_t’ from type
‘char *’
I tried casting out to cool_array_t but it gives the following error:
error: cast specifies array type
You cannot assign to arrays. You need to use memcpy or a wrapping struct.
struct cool_array_t {
char data[ARRAY_SIZE];
};
struct cool_array_t* out;
// do stuff with out
struct cool_array_t test = *out;

Resources