C Structures: Printing a string member produces weird results - c

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

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

Makefiles and structures in C

EDIT: To try and make things easier for the kind souls trying to help me, here are a couple links that should make things more clear:
Pre-makefile repl
Post-makefile repl
A little background on the assignment: We are supposed to take a program we wrote last week and break up the separate functions into their own files and use a makefile to compile and link and all that stuff. This is my original program (basically, it reads a file of name number and stores them in a struct, then uses the command line arguments to search for a name).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _data {
char* name;
long number;
};
int SCAN(FILE *(*input)) {
int lines = 0;
char word[50];
long num = 0;
while (1) {
fscanf(*input,"%s %ld",word, &num);
lines++;
if (feof(*input)) break;
}
return lines;
}
struct _data *LOAD(FILE *input, int size) {
char* line = NULL;
size_t len = 0;
int i=0;
rewind(input);
struct _data *book = calloc(size,sizeof(struct _data));
for (i = 0;i<size;i++) {
getline(&line, &len, input);
book[i].name = calloc(len+1,sizeof(char));
strcpy(book[i].name,strtok(line," "));
book[i].number = atoi(strtok(NULL, " "));
}
return book;
}
void SEARCH(struct _data *BlackBook, char *name, int size) {
int i;
for (i=0;i<size;i++) {
if (strcmp(name,BlackBook[i].name) == 0) {
printf("*******************************************\n");
printf("The name was found at the %d entry.\n",i+1);
printf("*******************************************\n");
break;
}
//If we reach the end of the array and name was not found
if (i == size-1) {
printf("*******************************************\n");
printf("The name was NOT found.\n");
printf("*******************************************\n");
}
}
}
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
//MAIN DRIVER ===================
int main(int argv, char** argc) {
int size;
char* filename = "hw5.data";
FILE *input = fopen(filename,"r");
size = SCAN(&input);
struct _data *phone_book = LOAD(input,size);
fclose(input);
//Check a name is given. If so, search
if (argv < 2) {
printf("*******************************************\n");
printf("* You must include a name to search for. *\n");
printf("*******************************************\n");
} else {
SEARCH(phone_book, argc[1], size);
}
FREE(phone_book,size);
return 0;
}
When I make my makefile, I can get the SCAN and LOAD functions to work appropriately. But, when I try to put either SEARCH or FREE into their own files, my compiler freaks out and I get warnings like:
In file included from hw6-free.c:1:0:
hw6-free.h:9:18: warning: ‘struct _data’ declared inside parameter list
void FREE(struct _data *BlackBook, int size);
^
hw6-free.h:9:18: warning: its scope is only this definition or declaration, which is probably not what you want
hw6-free.c:3:18: warning: ‘struct _data’ declared inside parameter list
void FREE(struct _data *BlackBook, int size) {
^
hw6-free.c:3:6: error: conflicting types for ‘FREE’
void FREE(struct _data *BlackBook, int size) {
^
In file included from hw6-free.c:1:0:
hw6-free.h:9:6: note: previous declaration of ‘FREE’ was here
void FREE(struct _data *BlackBook, int size);
^
hw6-free.c: In function ‘FREE’:
hw6-free.c:6:5: error: invalid use of undefined type ‘struct _data’
free(BlackBook[i].name);
^
hw6-free.c:6:19: error: dereferencing pointer to incomplete type ‘struct _data’
free(BlackBook[i].name);
^
Makefile:20: recipe for target 'hw6-free.o' failed
make: *** [hw6-free.o] Error 1
And reading through it, it looks like the fact my program takes a struct as an argument is my main problem? My 'post-makefile' program looks like:
#include "hw6-main.h"
int main(int argv, char** argc) {
int size;
char* filename = "hw5.data";
FILE *input = fopen(filename,"r");
size = SCAN(&input);
struct _data *phone_book = LOAD(input,size);
fclose(input);
//Check a name is given. If so, search
if (argv < 2) {
printf("*******************************************\n");
printf("* You must include a name to search for. *\n");
printf("*******************************************\n");
} else {
SEARCH(phone_book, argc[1], size);
}
FREE(phone_book,size);
return 0;
}
And my makefile looks like:
DEP = hw6-scan.o hw6-load.o hw6-search.o hw6-free.o hw6-main.o
HDR = hw6-scan.h hw6-load.h hw6-search.h hw6-free.h hw6-main.h
NAME = output
all: $(NAME)
output: $(DEP) $(HDR)
gcc $(DEP) $(HDR) -o $(NAME)
hw6-scan.o: hw6-scan.c
gcc -c hw6-scan.c
hw6-load.o: hw6-load.c
gcc -c hw6-load.c
hw6-search.o: hw6-search.c
gcc -c hw6-search.c
hw6-free.o: hw6-free.c
gcc -c hw6-free.c
hw6-main.o: hw6-main.c
gcc -c hw6-main.c
clean:
rm *.o *.gch *.out output testfile
As an example, my hw6-free.c and hw6-free.h look like:
#include "hw6-free.h"
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
and
#include <stdio.h>
#include <stdlib.h>
void FREE(struct _data *BlackBook, int size);
respectively.
And, finally, I defined the struct in the hw6-load.h file, along with a function prototype. Is that also a problem? Should I be defining it elsewhere?
I am SO SORRY for the long post, but I have been working on the for 10 hours and I'm about to throw my computer of a cliff.
THANK YOU FOR YOUR HELP STACK OVERFLOW!
This is an in-depth explanation of the details. It might be a bit too much, but if you keep reading, you may get a much deeper understanding of the language than if you just learn to write code that your compiler is ok with.
You are using your struct before you have declared it. Keep in mind that an #include is just a fancy way of telling your compiler: "Please, paste the contents of this .h file at this spot." The result of this pasting must read like valid code to the compiler.
It is true that the compiler's error message looks a bit weird. It certainly does not say "You used struct _data before you declared it". The reason for this is, that structs are implicitly declared at their first use. So, if you declare a variable with struct foo* bar; and the compiler has never seen a struct foo before, it will immediately consider struct foo as being declared, and a pointer variable to this struct foo of unknown size and shape will be defined. Likewise, when your compiler sees the function declaration
void foo(struct bar *baz);
it sees that it doesn't know a struct bar and implicitly declares one. Because this struct declaration happens inside a function declaration, the resulting type is declared local to the declaration at hand. As such, it is impossible for calling code to pass an argument of the correct type into this function, or even to implement the function in a separate statement. Such a function declaration is always useless. This is what the warning text "its scope is only this definition or declaration, which is probably not what you want" means: The compiler writers knew that such a declaration is bullshit, but it's legal C as far as the standard is concerned, so they compile it, but warn about it.
Ok, let's get to the actual error message. As the compiler tells you, the struct _data was only declared for the function declaration at hand. When your compiler later sees the function implementation, it stumbles across the undeclared struct _data a second time. Again, it implicitly declares a local struct type which is distinct from the previously implicitly declared type. Because those two implicitly declared types are distinct, so are the signatures of the declared functions. However, C mandates that a function can only have one signature, so the compiler produces the error "conflicting types for ‘FREE’".
You can try this out with this simple code:
void foo(struct bar* baz); //warning: local declaration of `struct bar`
void foo(struct bar* baz); //repeated warning + conflicting types error
So, how to fix this?
Simple. Declare your struct before you use it. That way you avoid its implicit declaration. The following code compiles fine:
struct bar; //global declaration of `struct bar`
void foo(struct bar* baz); //`struct bar` is known and the global declaration is used
void foo(struct bar* baz); //same as above, because this uses the same global declaration of `struct bar`, this redeclaration of `foo()` is ok
The declaration of the struct _data belongs into the header file that declares the functions which use struct _data as arguments.
Idiomatic declarations
Usually, types are declared with a typedef. This allows the code to omit the struct keyword when declaring variables. This takes one of two idiomatic forms:
To have a type with public members (pure data, no object in the OO sense), put the struct definition into the header:
typedef struct foo //`struct foo` is declared implicitly here
{ //it is also defined (= inner details are given) right here
int bar; //its member variables are defined
} baz; //this concludes the typedef, giving `struct foo` a second name
//`struct foo` and `baz` are now equivalent.
Usually, the two names will be the same or very similar, so the cleaned definition looks like this:
typedef struct foo {
int bar;
} foo;
//declarations of the functions that use `struct foo`
...
If the type is an object that should keep its data members to itself, the declaration and definitions are split like this:
Inside foo.h:
typedef struct foo foo; //declare that `struct foo` == `foo` exists, but don't give details
//declare the functions working on a `foo`
void foo_bim(foo* me);
void foo_bam(foo* me, ...);
...
Inside foo.c:
#include "foo.h" //so that the compiler may check that the function declarations in the header agree with the implementations in this file
struct foo { //define the size and shape of `struct foo` == `foo`
int bar;
};
//now only this file knows how a `struct foo` actually looks like
//implement the member functions of `foo`
void foo_bim(foo* me) {
...
}
void foo_bam(foo* me, ...) {
...
}
Note that the typedef ... non-struct-name; is purely optional in both cases, and there are quite a few programmers who want to see the struct keyword wherever a struct is used (like a certain Mr. Torvalds). These programmers simply leave off the typedef ... non-struct-name; part, otherwise they use the idioms above in the same way. I have described the full-featured version here, to ensure that you'll not be surprised when you first see the typedef construct.
I'm not sure what you did. But to step back: keep clear in your mind the difference between declarations and definitions. A declaration shows a variable or function signature, but does not create any variables of that type or implement that function. A definition declares a new variable (of some type) or implements a function. A declaration of a type just states that it exists (basically). A definition of a type shows its structure and members.
So, a definition of your type would be:
struct _data {
char* name;
long number;
};
And a declaration of a function would be:
void FREE(struct _data *BlackBook, int size);
and a definition of a function would be:
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
So here're the rules:
Only #include header files in other files, never #include source files.
If a type is needed in more than one file, put its definition into a header file and #include that header file in all source files that use the type.
If a function is used in more than one file, put the declaration of that function into a header file and #include that header file in all the source files that use the function, including the source file containing the definition of the function.
If you follow these rules you'll never run into duplicate definitions at link time: you can't have duplicate definitions if you link each source file only one time and no included file contains a definition.
Type declarations can be useful, and breaking some of these rules can be useful, but for the work you're doing that's probably not worth worrying about.
Try to put header of struct declaration at top of files which uses it and be sure you’ve imported the file which contains struct declaration.

Getting the error 'conflicting type for function',why?

Here is the below:why it comes out?
#include <stdio.h>
void iniStudentLink(struct STUDENT_LINK * L);
int main(){
return 0;
}
void iniStudentLink(struct STUDENT_LINK * L){
printf("hello world!\n");
}
showing the error : conflicting types for inniStudentLink.
These are the issues that come out of gcc when compiling your code (something it would have been handy to include in your question to make it more complete, that's just advice for the future):
testprog.c:3:28: warning: 'struct STUDENT_LINK' declared inside
parameter list will not be visible outside of
this definition or declaration
void iniStudentLink(struct STUDENT_LINK * L);
^~~~~~~~~~~~
testprog.c:9:28: warning: 'struct STUDENT_LINK' declared inside
parameter list will not be visible outside of
this definition or declaration
void iniStudentLink(struct STUDENT_LINK * L){
^~~~~~~~~~~~
testprog.c:9:6: error: conflicting types for ‘iniStudentLink’
void iniStudentLink(struct STUDENT_LINK * L){
^~~~~~~~~~~~~~
testprog.c:3:6: note: previous declaration of ‘iniStudentLink’ was here
void iniStudentLink(struct STUDENT_LINK * L);
^~~~~~~~~~~~~~
In other words, you are declaring two independent instances of the structure, without actually defining it(a). The reason they are considered independent is because their scope is limited to the actual function where they are being declared.
You can fix this by actually defining it so that the declarations both refer to that definition, such as with (before any other use):
struct STUDENT_LINK { int some_data; };
In other words, this compiles just fine:
#include <stdio.h>
struct STUDENT_LINK { int some_data; };
void iniStudentLink (struct STUDENT_LINK *L);
int main(void) { return 0; }
void iniStudentLink (struct STUDENT_LINK *L){ puts("hi!"); }
(although it may should warn you about the fact you don't actually use L in the function).
(a) The basic difference between declaring and defining in C is this:
Declaring means declaring that something exists without creating it, such as (in your case) stating that you want to pass a pointer-to-it to a function.
Defining it means literally that, defining what it is rather than just that it is.
Example declarations are extern int i; or struct xyzzy; wheras equivalent definitions would be int i; and struct xyzzy { int plugh; };.

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.

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

Resources