Newbie question

V

vadud3

Hi All

I am trying to compile the following program:

#include <stdio.h>
#include <string.h>

typedef struct employee {
int id;
char name[10];
float salary;
} e;

void processEmp(e); //supply function prototype with structure alias
name

main()
{
e empl = {0,'\0',0}; //Initialize members

processEmp (empl); //pass structure by value

printf("\nID: %d\n", empl.id);
printf("Name: %s\n", empl.name);
printf("Salary : $%.2f\n", empl.salary);
} // end main

void processEmp(e emp) //receives a copy of the structure
{
emp.id = 123;
strcpy(emp.name, "Sheila");
emp.salary = 65000.00;
} //end processEmp


I compile it using gcc 3.3.2 on Mandrake 10.2 like this

gcc program.c

But when I run ./a.out it shows

ID: 0
Name:
Salary : $0.00

I was expecting the output be like this:

ID: 123
Name: Sheila
Salary : $65000.00

Any thing I am doing wrong?

Thanks for the help
 
B

Ben Pfaff

vadud3 said:
processEmp (empl); //pass structure by value
[...]

void processEmp(e emp) //receives a copy of the structure
{
emp.id = 123;
strcpy(emp.name, "Sheila");
emp.salary = 65000.00;
} //end processEmp

You seem to have a fundamental misunderstanding of what "pass by
value" means. Look it up in your book again.
 
M

Martin Ambuhl

vadud3 said:
Hi All

I am trying to compile the following program:

OP's code replaced with:

#include <stdio.h>
#include <string.h>

typedef struct employee
{
int id;
char name[10];
float salary;
} employee;

void processEmp(employee *); /* note */

int main(void) /* note */
{
employee empl = { 0, "", 0 }; /* note */
processEmp(&empl); /* note */
printf("\nID: %d\n", empl.id);
printf("Name: %s\n", empl.name);
printf("Salary : $%.2f\n", empl.salary);
return 0; /* note */
}

void processEmp(employee * emp) /* note */
{
emp->id = 123; /* note */
strcpy(emp->name, "Sheila"); /* note */
emp->salary = 65000.00; /* note */
}


[output]
ID: 123
Name: Sheila
Salary : $65000.00
 
V

vadud3

That was how it was exactly in the book. I wonder if there might be
something very simple that came from the book as typo.
 
J

Jens.Toerring

vadud3 said:
That was how it was exactly in the book. I wonder if there might be
something very simple that came from the book as typo.

Then it might a good idea to throw away that book and get a better one.
It can't be a single typo and there are also several other problems with
the program.
#include <stdio.h>
#include <string.h>

typedef struct employee {
int id;
char name[10];
float salary;
} e;

void processEmp(e); //supply function prototype with structure alias
name

At least for posts in newsgroups better use the traditional "/*" and
"*/" comment delimiters - it makes it less error prone for others that
try to copy and paste the code when lines are too long and get broken
by the newsreader. Moreover, comments starting with "//" became only
legal with the newer C99 standard and they might get you into problems
with older compilers.

main() is a function that returns an int. Relying on that being the
default isn't an option anymore if your program is to be compiled
with a C99 compliant compiler. And it's also clearer to specify the
arguments main() is supposed to accept, i.e. none. So make that line

int main( void )
{
e empl = {0,'\0',0}; //Initialize members

The second member of the employee structure is a char array, not a
char, so the initialization must be either

e empl = { 0, "", 0 };

or

e empl = { 0, { '\0' }, 0};
processEmp (empl); //pass structure by value

And this means that the function receives a copy of the structure.
Everything done by that function gets done to the copy it received
but not to the structure you have in the caller of the function,
which remains unchanged. As Martin Ambuhl already pointed out you
can correct that by passing a pointer to the structure to the func-
tion and operate on the structure belonging to the caller via this
pointer. Another option would be to have the function return the
modified structure and to assign this return value to 'empl'.
printf("\nID: %d\n", empl.id);
printf("Name: %s\n", empl.name);
printf("Salary : $%.2f\n", empl.salary);
} // end main

Since main() returns an int you're missing a return statement here.
Use either

return EXIT_SUCCESS;

(but then you need to include <stdlib.h>) or

return 0;

on successful exit from main().

Some of the problems the compiler can tell you about if you invoke it
with the appropriate options. In the case of gcc I would recommend to
use at least "-W -Wall" - it then will warn you about code that is
problematic.
Regards, Jens
 
B

Barry Schwarz

That was how it was exactly in the book. I wonder if there might be
something very simple that came from the book as typo.

If you tell us which book, we can add it to the list of ones to be
avoided.


<<Remove the del for email>>
 
D

Darklight

It looks like you are using linux so may i suggest you use the following
commands IE:

gcc -Wall file.c

to compile will give you better error output
or

gcc -Wall -ggdb file.c -o file

which will enable you to run the ddd debugger but it must be installed
then to run the debbeger you type ddd file
file being the executable file

right i am a beginner so the program you wrote is below with the
modifications i made the rest you will have to work out for your self.

#include <stdio.h>
#include <string.h>

struct employee {
int id;
char name[10];
float salary;
}emp;

void processEmp(void); /*supply function prototype with structure alias*/

int main(void)
{
processEmp (void); /*pass structure by value*/

printf("\nID: %d\n", emp.id);
printf("Name: %s\n", emp.name);
printf("Salary : $%.2f\n", emp.salary);
return 0;
} /* end main */

void processEmp(void) /*receives a copy of the structure*/
{
emp.id = 123;
strcpy(emp.name, "Sheila");
emp.salary = 65000.00;
} /*end processEmp*/
 
M

Michael Mair

Darklight said:
It looks like you are using linux so may i suggest you use the following
commands IE:

gcc -Wall file.c

More important: Tell the compiler that you want to have standard
conforming C!

gcc -Wall -ansi -pedantic

If you add weak optimisation, you get more information about
unused variables and the like:

gcc -O -Wall -ansi -pedantic

If you want to have whatever C99 gcc already has, use -std=c99 instead
of -ansi.
If you do not want to type this all the time, use an alias for gcc.
to compile will give you better error output
or

gcc -Wall -ggdb file.c -o file

which will enable you to run the ddd debugger but it must be installed
then to run the debbeger you type ddd file
file being the executable file

ddd works on top of gdb, hence the -ggdb.
This option does not give you more warnings but makes the code
debuggable by leaving correlations between lines in source and
the executed object code in the object file.
I would use extensive debug information if any: -g3 or -ggdb3
This makes macros partially usable in debugging (the ## and #
operators do not work).
right i am a beginner so the program you wrote is below with the
modifications i made the rest you will have to work out for your self.

#include <stdio.h>
#include <string.h>

struct employee {
int id;
char name[10];
float salary;
}emp;

You are declaring (and using) a global variable emp. This is a
Bad Idea in many if not most situations; if you do not understand
that then be careful with "advice" you give to other people.

void processEmp(void); /*supply function prototype with structure alias*/

We have a function which does not get passed anything and returns
nothing. The comment is definitely wrong.
int main(void)
{
processEmp (void); /*pass structure by value*/

The comment is wrong. It should read:
/* Initialise global variable emp */
printf("\nID: %d\n", emp.id);
printf("Name: %s\n", emp.name);
printf("Salary : $%.2f\n", emp.salary);
return 0;
} /* end main */

void processEmp(void) /*receives a copy of the structure*/

Once more: The comment is bogus.
{
emp.id = 123;
strcpy(emp.name, "Sheila");

Careful: either check whether strlen("Sheila")+1<=sizeof(emp.name)
or use strncpy() or your own safe version of it.
emp.salary = 65000.00;
} /*end processEmp*/

If you work only on global variables, you run into trouble whenever
you need another variable: You have to double the number of functions
even if the functions do essentially the same.
Read up on this and the structural dangers of using global variables.

For the OP: Stay with Martin Ambuhl's solution and ask if you
do not understand it from the comments already given in the
thread.


Cheers
Michael
 
F

Flash Gordon

Darklight said:
It looks like you are using linux so may i suggest you use the following
commands IE:

gcc -Wall file.c

Around here you should really use -ansi -pedantic as well, so that you
invoke it as a conforming C compiler. Adding -O allows another warning
to be generated.

gcc -ansi -pedantic -Wall -O file.c
to compile will give you better error output
or

gcc -Wall -ggdb file.c -o file

gcc -ansi -pedantic -Wall -O -g file.c -o file
which will enable you to run the ddd debugger but it must be installed
then to run the debbeger you type ddd file
file being the executable file

right i am a beginner so the program you wrote is below with the
modifications i made the rest you will have to work out for your self.

#include <stdio.h>
#include <string.h>

struct employee {
int id;
char name[10];
float salary;
}emp;

Using globals is generally a *bad* idea.
void processEmp(void); /*supply function prototype with structure alias*/

You are write to supply a function prototype. However, see comments
about how this problem should have been solved.
int main(void)
{
processEmp (void); /*pass structure by value*/

Your comment is now completely wrong. A good way to confuse people.
printf("\nID: %d\n", emp.id);
printf("Name: %s\n", emp.name);
printf("Salary : $%.2f\n", emp.salary);
return 0;
} /* end main */

void processEmp(void) /*receives a copy of the structure*/

Your comment is now completely wrong. A good way to confuse people.
{
emp.id = 123;
strcpy(emp.name, "Sheila");
emp.salary = 65000.00;
} /*end processEmp*/

I suggest you look at the other replies. Using a global variable is
*not* the right thing to do. You either pass a pointer to the struct or
make the function return the struct.
 
J

Jonathan Burd

vadud3 said:
Hi All

I am trying to compile the following program:

#include <stdio.h>
#include <string.h>

typedef struct employee {
int id;
char name[10];
float salary;
} e;

void processEmp(e); //supply function prototype with structure alias
name

main()
{
e empl = {0,'\0',0}; //Initialize members

processEmp (empl); //pass structure by value

printf("\nID: %d\n", empl.id);
printf("Name: %s\n", empl.name);
printf("Salary : $%.2f\n", empl.salary);
} // end main

void processEmp(e emp) //receives a copy of the structure
{
emp.id = 123;
strcpy(emp.name, "Sheila");
emp.salary = 65000.00;
} //end processEmp


I compile it using gcc 3.3.2 on Mandrake 10.2 like this

gcc program.c

But when I run ./a.out it shows

ID: 0
Name:
Salary : $0.00

I was expecting the output be like this:

ID: 123
Name: Sheila
Salary : $65000.00

Any thing I am doing wrong?

Thanks for the help

I would suggest you drop the book you are reading. Get a better book
like the one written by K. N. King (C Programming: A Modern Approach).
Steer clear from Schildt's stuff, unless you want an exercise finding bugs.

Regards,
Jonathan
 
C

Chris Torek

vadud3 said:
typedef struct employee {
int id;
char name[10];
float salary;
} e; [and]
e empl = {0,'\0',0}; //Initialize members

The second member of the employee structure is a char array, not a
char, so the initialization must be either

e empl = { 0, "", 0 };

or

e empl = { 0, { '\0' }, 0};

While either of these is, in my opinion, clearly *superior*, it
is not the case that these are *required* (implied by the words
"must be"). Without additional bracketing, what we have is, in
effect:

{
empl.id = 0,
empl.name[0] = '\0',
empl.name[1] = 0
/*
* empl.name[2] = 0 -- no explicit initializer, hence defaulted
* empl.name[3] = 0 -- no explicit initializer
* .
* .
* .
* empl.name[9] = 0 -- no explicit initializer
* empl.salary = 0 -- no explicit initializer
*/
}

Without explicit initializers for the listed elements, the fact
that there is some initializer at all causes the rest of the
initializers to be created implicitly by the compiler as if you
had explicitly asked for each one to be set to 0.

This is the same rule that, given:

void f(void) {
char buf[12345] = { 0 };
...
}

forces the C compiler to initialize all 12345 elements of the
array "buf" to 0. If we change the source to:

void f(void) {
char buf[12345];
buf[0] = 0;
...
}

the compiler is not obligated to zero out all 12344 remaining
elements, and most will indeed not do so. (In a few rare cases,
this can even make f() run faster-enough to notice. :) )
 
J

Jens.Toerring

Chris Torek said:
typedef struct employee {
int id;
char name[10];
float salary;
} e; [and]
e empl = {0,'\0',0}; //Initialize members
While either of these is, in my opinion, clearly *superior*, it
is not the case that these are *required* (implied by the words
"must be").

Thanks for the clarification. The "must be" was wrong unless under-
stood in the sense that it doesn't do what the OP probably meant the
code to do, i.e. an initialization of

empl.id = 0;
empl.name[0] = '\0';
empl.salary = 0;

and that it wouldn't work as expected with e.g.

e empl = { 0, '\0', 10 };

because in that case empl.salary wouldn't be set to 10, as I guess
the OP did assume, but empl.name[1].

Regards, Jens
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

C doubt(const variable) 9
Dont copy the output 0
Reading a number from stdin 1
stylistic question 16
[Newbie] qsort question 3
Newbie pointers and reversing question 37
newbie question 6
dequeue() not working 9

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top