Functions, arrays, structs and passing by reference

S

S.

Hi all,

Can someone please help me with this?

I have the following struct:
typedef struct {
char *name;
int age;
} Student;


I have the following prototype declaration:
void addStudent(Student *arr_students);

In my main, I want to have an array called 'students' which is
composed of the Student struct. I then want to pass a function that
will allow me to create a Student record using pass-by-reference:
int main() {

Student students[CLASSSIZE]; /* array of student
struct's? */

addStudent(&students[0]);
printf("%s",&students[0].name);
return 0;
}

The following is my function to add a student:
void addStudent(Student *arr_student) {
char *name;

printf("\nEnter student name: ");
scanf("%s",&name);
*arr_student[0].name = name;

return;
}

I guess I have two questions before everyone dives into how wrong I
have done everything.
Q1. When I compile this I get the following error, could someone
please help explain why this occurs and how I can fix my code to
prevent this warning?
"test.c", line 25: warning: improper pointer/integer
combination: op "="
Q2. When I run my program, I am prompted with "Enter student name: "
and I enter in a name, I then receive the following error, can someone
please explain why this is happening too?
"Segmentation Fault"

I have a feeling I have declared my array of Student struct wrong and
I am also not passing the array through to the function correctly
which is causing both my problems. I have searched all over the
internet and in this discussion group but can't find an example
related to what I am trying to do.

Any help would be appreciated.

Kind regards,
S.

Below is my program:
#include <stdio.h>
#define CLASSSIZE 10

typedef struct {
char *name;
int age;
} Student;

void addStudent(Student *arr_students);

int main() {

Student students[CLASSSIZE]; /* array of student struct's?*/

addStudent(&students[3]);
printf("%s",&students[3].name);
return 0;
}

void addStudent(Student *arr_student) {
char *name;

printf("\nEnter student name: ");
scanf("%s",&name);
*arr_student[3].name = name;

return;
}
 
J

Jim Langston

S. said:
Hi all,

Can someone please help me with this?

I have the following struct:
typedef struct {
char *name;
int age;
} Student;


I have the following prototype declaration:
void addStudent(Student *arr_students);

In my main, I want to have an array called 'students' which is
composed of the Student struct. I then want to pass a function that
will allow me to create a Student record using pass-by-reference:
int main() {

Student students[CLASSSIZE]; /* array of student
struct's? */

addStudent(&students[0]);
printf("%s",&students[0].name);
return 0;
}

The following is my function to add a student:
void addStudent(Student *arr_student) {
char *name;

printf("\nEnter student name: ");
scanf("%s",&name);
*arr_student[0].name = name;

return;
}

I guess I have two questions before everyone dives into how wrong I
have done everything.
Q1. When I compile this I get the following error, could someone
please help explain why this occurs and how I can fix my code to
prevent this warning?
"test.c", line 25: warning: improper pointer/integer
combination: op "="
Q2. When I run my program, I am prompted with "Enter student name: "
and I enter in a name, I then receive the following error, can someone
please explain why this is happening too?
"Segmentation Fault"

I have a feeling I have declared my array of Student struct wrong and
I am also not passing the array through to the function correctly
which is causing both my problems. I have searched all over the
internet and in this discussion group but can't find an example
related to what I am trying to do.

Any help would be appreciated.

Kind regards,
S.

Below is my program:
#include <stdio.h>
#define CLASSSIZE 10

typedef struct {
char *name;

name is declared as a pointer to a char (or char array).
int age;
} Student;

void addStudent(Student *arr_students);

int main() {

Student students[CLASSSIZE]; /* array of student struct's?*/

addStudent(&students[3]);
printf("%s",&students[3].name);
return 0;
}

void addStudent(Student *arr_student) {
char *name;

name here is a local variable that can hold a pointer to a character or
character array. Only the size of a pointer is allocated to it. It is not
pointing at anything at this point, some random bit of memory maybe, or
maybe 0
printf("\nEnter student name: ");
scanf("%s",&name);

You are now trying to store the characters entered at the location that name
is pointing to... but, name is still pointing into lala land. No memory has
actually been allocated to hold the characters entered.
*arr_student[3].name = name;

return;
}

Now, you can, to fix this in your current design, malloc memory in
addStudent to hold the student name and point the structure name to it, but
thinknig about it, you're going to have to set some size. 10? 20? 30?
Whatever it is, it probably won't be big enough. Anyway, why go through all
this trouble because then you have to free the memory when your program is
done. You might as well just allocate it in your structure in the first
place.

typedef struct {
char name[30];
int age;
} Student;

now you can just scanf("%s", arr_student->name )
 
N

Nick Keighley

I have the following struct:
typedef struct {
        char *name;
        int age;

} Student;

I have the following prototype declaration:
void addStudent(Student *arr_students);

In my main, I want to have an array called 'students' which is
composed of the Student struct. I then want to pass a function that
will allow me to create a Student record using pass-by-reference:

C doesn't support pass-by-reference (I'm not just being pedantic
I think its part of your problem). In C all arguments are passed by
value. You can pass pointers which comes close to emulating
call-by-reference.

int main() {

        Student students[CLASSSIZE];  /* array of student
struct's?      */

yes that's fine

        addStudent(&students[0]);

ok
using => to mean "type is"

students => Student[] => array-of-Student
students[0] => Student
&students[0] => Student* => ptr-to-Student

which is what the function wants.

        printf("%s",&students[0].name);

what's the & for?

students[0].name => char*
&students[0].name => char

oops! printf() is expecting a char* and you gave it a char
        return 0;

}

The following is my function to add a student:
void addStudent(Student *arr_student) {

I find the name confusing. arr_student is NOT an
array of Students but a pointer to a student.

        char *name;

        printf("\nEnter student name: ");
        scanf("%s",&name);

bang! name is pointing a random memory
(or no memory at all)
        *arr_student[0].name = name;

Like I said arr_student isn't an array...

Ok, I'm confused are you trying to pass a single Student or an
array. C may not distinguish these cases but you need to be
clear in your mind which you are trying to do. Does addStudent()
add a single student? There's no loop so I assume so. So logically
addStudent only needs a single Student.

arr_student => Student*
arr_student[0] => Student
arr_student[0].name => char*
*arr_student[0].name => char

You probably want

(*arr_student).name

or the shortcut notation

arr_student->name
        return;

}

I guess I have two questions before everyone dives into how wrong I
have done everything.
Q1. When I compile this I get the following error, could someone
please help explain why this occurs and how I can fix my code to
prevent this warning?
           "test.c", line 25: warning: improper pointer/integer
combination: op "="

I'd have to compile your program to find out which line is
line 25. Couldn't you just tell us?
Q2. When I run my program, I am prompted with "Enter student name: "
and I enter in a name, I then receive the following error, can someone
please explain why this is happening too?
           "Segmentation Fault"

I have a feeling I have declared my array of Student struct wrong
nope

and
I am also not passing the array through to the function correctly
which is causing both my problems.

I don't think you want an array...
I have searched all over the
internet and in this discussion group but can't find an example
related to what I am trying to do.

Below is my program:

you effectivly posted it twice...

        *arr_student[3].name = name;

3?
 
H

Harald van Dijk

        printf("%s",&students[0].name);

what's the & for?

students[0].name => char*
&students[0].name => char

oops! printf() is expecting a char* and you gave it a char

If students[0].name has type char*, then &students[0].name has type
char**. It's still wrong, of course.
 
S

S.

Hi all,

Thank you so much for your help. I have amended the code based on Jim
Langston's and Nick Keighley's comments. The specifics are as follows:
i. Changed the Student struct "name" variable from a pointer to a size
specified array - turned it into string array
ii. Changed the scanf to be: scanf("%s", arr_student->name )
ii. Renamed "arr_student" parameter of the addStudent function to
"student" because as Nick stated, this is not an array, but a student
being passed through

All errors appear resolved and there are no warnings. Program runs
squeaky.

Kind regards,
S.
 
J

Jim Langston

S. said:
Hi all,

Thank you so much for your help. I have amended the code based on Jim
Langston's and Nick Keighley's comments. The specifics are as follows:
i. Changed the Student struct "name" variable from a pointer to a size
specified array - turned it into string array
ii. Changed the scanf to be: scanf("%s", arr_student->name )
ii. Renamed "arr_student" parameter of the addStudent function to
"student" because as Nick stated, this is not an array, but a student
being passed through

All errors appear resolved and there are no warnings. Program runs
squeaky.

For now. Try entering a name longer than the size you've allocated for
name. This produces undefined behavior.

You need to make sure that your data array doesn't get overflown
(overflowed?), which can happen here. I don't believe this can be done with
scanf though, you'll need to use some other input routine.
 
B

Barry Schwarz

Hi all,

Can someone please help me with this?

I have the following struct:
typedef struct {
char *name;
int age;
} Student;


I have the following prototype declaration:
void addStudent(Student *arr_students);

The name of the parameter is not needed. However, if you use one it
should not be misleading like this one.
In my main, I want to have an array called 'students' which is
composed of the Student struct. I then want to pass a function that
will allow me to create a Student record using pass-by-reference:

In C, all argument passing and all return passing is done by value.
While passing an address has some similarities to pass by reference,
it is only some.
int main() {

int main(void) is more precise.
Student students[CLASSSIZE]; /* array of student
struct's? */

addStudent(&students[0]);
printf("%s",&students[0].name);
return 0;
}

The following is my function to add a student:
void addStudent(Student *arr_student) {
char *name;

printf("\nEnter student name: ");
scanf("%s",&name);
*arr_student[0].name = name;

Since . binds more tightly than *, this is treated as
*(arr_student[0].name) = name;
What type is member name of your struct? What is the type when you
dereference this member? What is the type of the variable name? Are
these types compatible? Do you see the similarity between these two
types and the text of the error message?
return;
}

I guess I have two questions before everyone dives into how wrong I
have done everything.
Q1. When I compile this I get the following error, could someone
please help explain why this occurs and how I can fix my code to
prevent this warning?
"test.c", line 25: warning: improper pointer/integer
combination: op "="

Do not attempt to assign a pointer value to an integer variable.
Q2. When I run my program, I am prompted with "Enter student name: "
and I enter in a name, I then receive the following error, can someone
please explain why this is happening too?
"Segmentation Fault"

You attempt to read character data into an area reserved for the value
of the name. You then try to pass this character data to printf as an
address. Character data usually does not form a good address. Once
printf tries to access the data at this wild address, you have entered
the realm of undefined behavior. A seg fault is one of the better
possible outcomes.
I have a feeling I have declared my array of Student struct wrong and

There is nothing wrong with your array definition.
I am also not passing the array through to the function correctly
which is causing both my problems. I have searched all over the

You do not pass the array to the function at all. You do pass the
address of the first element of the array and you do that properly.
You have to make a design decision about how to process the other
elements of the array. One option would be to loop in main and pass
&students instead of [0]. Another would be to have addStudent loop
through multiple elements by incrementing the pointer in each
iteration. (But then you should change the name to addStudents.)
internet and in this discussion group but can't find an example
related to what I am trying to do.

You are biting off too much at one time. Forget the array of struct,
maybe even the struct itself. Start with a program that successfully
reads a name, stores it somewhere safely, and then prints it out (to
verify the first to steps). Then expand to store the name in a single
instance of the struct. Then expand to read the age and print both
members of the struct. Then start thinking about an array of struct.
Any help would be appreciated.

Kind regards,
S.

Below is my program:

We only need to see it once.


Remove del for email
 
D

David Thompson

S. wrote:

For now. Try entering a name longer than the size you've allocated for
name. This produces undefined behavior.

You need to make sure that your data array doesn't get overflown
(overflowed?), which can happen here. I don't believe this can be done with
scanf though, you'll need to use some other input routine.

*scanf does allow input length limits, which for %s (and %[...] and
%c) translate directly into limits on the amount stored:
struct { ... char a [20]; ... } x; ...
if( scanf ("%19s", x.a) != 1 ) error;
/* 19 because %s or %[] stores a null terminator */

This is obviously a maintenance problem, and you can't automate it by
using the * modifier as you can for *printf. You can do either of:
- macro-stringize the limit, as a simple decimal constant only, into
the format, and use that same limit plus one to allocate the storage
- runtime-generate the format: can use sizeof(obj)-1 for the value.

Obviously these aren't ideal, and IMO&E are never the best solution to
this type of problem; but they are possible.

PS: 'overflowed' is correct. But you can avoid the issue by using
'overrun' instead: its participle is the same as its present.

- formerly david.thompson1 || achar(64) || worldnet.att.net
 

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

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,813
Latest member
lawrwtwinkle111

Latest Threads

Top