Functions, arrays, structs and passing by reference

Discussion in 'C Programming' started by S., May 1, 2008.

  1. S.

    S. Guest

    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;
    }
     
    S., May 1, 2008
    #1
    1. Advertising

  2. S.

    Jim Langston Guest

    S. wrote:
    > 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 )


    --
    Jim Langston
     
    Jim Langston, May 1, 2008
    #2
    1. Advertising

  3. On 1 May, 02:41, "S." <> wrote:

    > 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.


    <snip>

    > Below is my program:


    you effectivly posted it twice...

    <snip>

    >         *arr_student[3].name = name;


    3?


    --
    Nick Keighley

    "The Dinosaurs have come and gone,
    we Theriodonts remain"
     
    Nick Keighley, May 1, 2008
    #3
  4. On Thu, 01 May 2008 02:50:00 -0700, Nick Keighley wrote:
    > On 1 May, 02:41, "S." <> wrote:
    >>         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.
     
    Harald van Dijk, May 1, 2008
    #4
  5. S.

    S. Guest

    Re: Functions, arrays, structs and passing by reference [SOLVED]

    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.
     
    S., May 1, 2008
    #5
  6. S.

    Jim Langston Guest

    Re: Functions, arrays, structs and passing by reference [SOLVED]

    S. wrote:
    > 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.

    --
    Jim Langston
     
    Jim Langston, May 1, 2008
    #6
  7. On Wed, 30 Apr 2008 18:41:40 -0700 (PDT), "S." <>
    wrote:

    >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
     
    Barry Schwarz, May 2, 2008
    #7
  8. Re: Functions, arrays, structs and passing by reference [SOLVED]

    On Thu, 1 May 2008 15:11:50 -0700, "Jim Langston"
    <> wrote:

    > S. wrote:


    > > ii. Changed the scanf to be: scanf("%s", arr_student->name )


    > > 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.


    *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
     
    David Thompson, May 12, 2008
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Patricia  Van Hise

    structs with fields that are structs

    Patricia Van Hise, Apr 5, 2004, in forum: C Programming
    Replies:
    5
    Views:
    642
    Al Bowers
    Apr 5, 2004
  2. Chris Hauxwell

    const structs in other structs

    Chris Hauxwell, Apr 23, 2004, in forum: C Programming
    Replies:
    6
    Views:
    561
    Chris Hauxwell
    Apr 27, 2004
  3. spleen

    passing structs in and out of functions

    spleen, Jan 29, 2005, in forum: C Programming
    Replies:
    2
    Views:
    293
    Neil Kurzman
    Feb 1, 2005
  4. Paul N

    Passing structs to functions

    Paul N, Oct 7, 2009, in forum: C++
    Replies:
    5
    Views:
    403
    Sudarshan Narasimhan
    Oct 10, 2009
  5. WTH
    Replies:
    1
    Views:
    223
Loading...

Share This Page