Passing struct to a function to assign values - c

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.

Related

Double linked list2

I did a lot of linked lists already,
but I didn't use them for a while and didn't really programm anything, therefore I am litterally lost.
The following is my Code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int age;
int pers_num;
char name[100];
void *previous;
void *next;
}Person;
int main(){
Person first_element;
Person last_element;
first_element.next = (Person *)(&last_element);
last_element.age = 19;
printf("%d\n",(&last_element)->age);
printf("%d\n",(first_element.next)->age);
}
Could you explain to me why following error is thrown?
speicher.c: In function 'main':
speicher.c:22:39: warning: dereferencing 'void *' pointer
23 | printf("%d\n",(first_element.next)->age);
| ^~
speicher.c:23:39: error: request for member 'age' in something not a structure or union
As I understand it "first_element.next" should be the pointer which points at last_element.
therefore you should be able to use the -> to access the data inside last_element.
The line 22 Runs perfectly even thought it should have the same Output as line 23, where the error is thrown.
You can't dereference a void pointer because it's a pointer that references a void type :-) In other words, it doesn't really know what actual type it points at. The reason why the two lines behave differently are, keeping in mind that a->b is just syntactic sugar for (*a).b:
printf("%d\n",(&last)->age);
// This (&last)->age, which is actually the same
// as last.age. In both cases, the type being used
// to get the age field is Person, so no problem.
printf("%d\n",(first.next)->age);
// This (first.next)->age is the same as
// (*(first.next)).age. Because first.next is of type
// void *, it cannot be dereferenced.
What you are doing is akin to declaring a variable with void x, which is not valid (don't confuse that with void *x which is valid).
You would be better off (within the structure) pointing to the actual type you want, with something like:
typedef struct s_Person { // A
int age;
int pers_num;
char name[100];
struct s_Person *previous, *next;
} Person; // B
Note that you cannot use the Person type definition while you're creating it, since it does not yet exist. Simplistically, you can think of it coming into existence at the B point. The named structure s_Person comes into existence at A so it can be used within the structure.

C Structures: Printing a string member produces weird results

I am independently learning C. I have a four member struct as follows:
#define aSize 10
struct Students {
char lastName[aSize];
char firstName[aSize];
int age;
int grade;
}
I have two separate functions (in the main.c file):
void pasteInfo_1(struct Students S1) {}
and
void printStudents(struct Students S1) {}
pasteInfo() uses strcpy() and assignment to assign values to the members; printStudents() then prints the values stored in the members. When I compile the file:
#in makefile
CFLAGS = -lm -o -Wall
gcc main.c $(CFLAGS) main
It compiles with no errors. However, when I call the executable it prints some very weird characters that look like binary/assembly. Any suggestions? Here are the individual functions.
void pasteInfo_1(struct Students S1) {
strcpy(S1.lastName, "Effinger");
}
And here is printStudents:
void printStudents(struct Students S1) {
printf("%s\n",S1.lastName);
}
The function calls in main:
int main() {
struct Students S1;
pasteInfo_1(S1);
printStudents(S1);
}
Re: Modifications.
After adding the changes suggested by user3629249, I got the following errors:
main.c:6:23: warning: ‘struct Students’ declared inside parameter list will not be visible outside of this definition or declaration
void pasteInfo(struct Students * pS1);
^~~~~~~~
main.c:7:27: warning: ‘struct Studens’ declared inside parameter list will not be visible outside of this definition or declaration
void printStudents(struct Studens S1);
^~~~~~~
main.c: In function ‘main’:
main.c:22:14: warning: passing argument 1 of ‘pasteInfo’ from incompatible pointer type [-Wincompatible-pointer-types]
pasteInfo( &S1);
^
main.c:6:6: note: expected ‘struct Students *’ but argument is of type ‘struct Students *’
void pasteInfo(struct Students * pS1);
^~~~~~~~~
main.c:23:17: error: type of formal parameter 1 is incomplete
printStudents(S1);
^~
main.c: At top level:
main.c:26:6: error: conflicting types for ‘pasteInfo’
void pasteInfo(struct Students * pS1)
^~~~~~~~~
main.c:6:6: note: previous declaration of ‘pasteInfo’ was here
void pasteInfo(struct Students * pS1);
^~~~~~~~~
main.c:32:6: error: conflicting types for ‘printStudents’
void printStudents(struct Students S1)
^~~~~~~~~~~~~
main.c:7:6: note: previous declaration of ‘printStudents’ was here
void printStudents(struct Studens S1);
^~~~~~~~~~~~~
It seems from your error messages as though you need to forward declare struct Students and/or pasteInfo. See your textbook for advice on how to do that, if necessary.
I am independently learning C.
What does this mean? Are you reading from a book? If so, which book?
Keep in mind that it's dangerous to learn C by misguided trial and error; what you'll most likely end up learning is something that differs from C in subtle and possibly dangerous ways, and which medications best deal with the headaches you give yourself...
That's the peril of learning by misguided trial and error; you'll run into a lot of undefined behaviour (and implementation-defined behaviour) that will differ from system to system and might not make sense at the time...
You're better off avoiding UB and IB by reading a decent book such as K&R2E, and doing the exercises as you stumble across them.
when the called function plans to (directly) change anything in the caller function, pass the address of the item to the called function. I.E.
int main( void )
{
struct Students S1;
pasteInfo_1( &S1 ); // <-- passing pointer to struct
printStudents( S1 );
}
Then modify the pasteInfo_1()` function to expect a pointer,
void pasteInfo_1( struct Students * pS1 )
{
strcpy( pS1->lastName, "Effinger" );
}
Note the use of vertical alignment of the braces and the use of appropriate horizontal spacing.
The purpose of the vertical alignment and horizontal spacing is to make the code much more readable.
Solved it! Here is the working code:
(Special Thanks to user3629249 and Seb for their advice)
'#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
struct Students
{
char lastName[8];
char firstName[6];
int age;
int grade;
};
void pasteInfo(struct Students *S1);
void printStudnets(struct Students S1);
int main(void)
{
struct Students S1;
pasteInfo( &S1 );
printStudents( S1 );
}
void pasteInfo(struct Students *S1)
{
strcpy(S1->lastName, "Effinger");
}
void printStudent(struct Students S1)
{
printf("%s\n",S1.lastName);
}

compilation error: conflicting types for 'modify' - why?

Why am I getting compilation error for below code.
#include <stdio.h>
void modify(struct emp *y);
struct emp
{
char name[20];
int age;
};
main()
{
struct emp e={"foo",35};
modify(&e);
printf("\n%s%d",e.name,e.age);
}
void modify(struct emp *p){
strupr(p->name);
p->age = p->age+2;
}
Below is the part of build log messages.
error: conflicting types for 'modify'| at line no. 15
note: previous declaration of 'modify' was here| at line no. 3
gcc can tell you the reason.
Increase your warning level:
prog.c:3:20: warning: 'struct emp' declared inside parameter list
void modify(struct emp *y);
^
prog.c:3:20: warning: its scope is only this definition or declaration, which is
probably not what you want
You can either change the order of the prototype and the struct definition, or add a declaration of the struct before the prototype.
Move the struct upwards so your function prototype knows emp
struct emp
{
char name[20];
int age;
};
void modify(struct emp *y);
int main(void)
{
struct emp e={"foo",35};
modify(&e);
printf("\n%s%d",e.name,e.age);
return 0;
}
void modify(struct emp *p){
p->age = p->age+2;
}
The declaration of main() is incorrect. The function should return an integer: return 0;, and the return type should be specified explicitly:
int main(void)
{
/* ... */
return 0;
}
Prototype of modify function mentions undeclared structure emp. In other words, you should put the declaration of emp structure before the prototype.
Avoid using strupr as it is non-standard function.
Consider declaring functions static, if they are supposed to be used only within the current compilation unit.
Moving the definitions around will fix the issue for you. But since no one mentioned it yet, I'll pitch in:
You can fix it with the minimal change of forward declaring the struct.
struct emp; // Forward declare struct emp before using it in the prototype.
void modify(struct emp *y);

Incomplete type error in C while using structures

Hello i encoutnered a problem.
Here is my header file with structure definition and a method prototype.
typedef struct SymbolTable
{
...some elements
}ST;
extern struct ST STable;
void Symbol_Put(ST *S, char* sym);
In my c program i use:
#include "myheader.h"
struct ST STable;
and in the method i am using methods from header file.
...body of the method...
int id = Symbol_Put(STable,sym_name);
Unfortuneately i am getting this error:
‘STable’ has an incomplete type
int s = Symbol_Put(STable,sym_name)
I don't understand what is wrong. I would be grateful for pointing me where i made a mistake. Thanks!
There is no struct ST in your code. There's only struct SymbolTable and ST.
Change the declaration to
extern ST STable;
and the definition to
ST STable;
Symbol_Put expects a pointer as the first argument but you pass a ST. Replace the invocations by
int id = Symbol_Put(&STable,sym_name);

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.

Resources