dynamic char * length in a struct 
Author Message
 dynamic char * length in a struct

typedef struct student {
  struct student *next;
  char *name;

Quote:
} student_t;

/* skipped */

/* start of a function */
char data[30];
student_t *a;

scanf(" %s", data);

/*
 * how to allocate memory for "a"
 * according to the length of data?
 * I do it this way, but the program crashed
 */

a = (student *) malloc(sizeof(student_t) + strlen(data) + 1);
strcpy(a->name, data);

/* thanks in advance */



Wed, 13 Apr 2005 01:56:50 GMT  
 dynamic char * length in a struct

Quote:

> typedef struct student {
>   struct student *next;
>   char *name;
> } student_t;

> /* skipped */

> /* start of a function */
> char data[30];
> student_t *a;

> scanf(" %s", data);

This isn't safe.  If the user enters more than will fit in
data[], undefined behavior results.

Quote:
> a = (student *) malloc(sizeof(student_t) + strlen(data) + 1);

When calling malloc(), I recommend using the sizeof operator on
the object you are allocating, not on the type.  For instance,
*don't* write this:

        int *x = malloc (sizeof (int) * 128); /* Don't do this! */

Instead, write it this way:

        int *x = malloc (sizeof *x * 128);

There's a few reasons to do it this way:

        * If you ever change the type that `x' points to, it's not
          necessary to change the malloc() call as well.

          This is more of a problem in a large program, but it's still
          convenient in a small one.

        * Taking the size of an object makes writing the statement
          less error-prone.  You can verify that the sizeof syntax is
          correct without having to look at the declaration.

I don't recommend casting the return value of malloc():

        * The cast is not required in ANSI C.

        * Casting its return value can mask a failure to #include
          <stdlib.h>, which leads to undefined behavior.

        * If you cast to the wrong type by accident, odd failures can
          result.

In addition, you seem to have a fundamental misconception of how
pointers work.  You can't just assign to `a' and expect that
`a->name' is also magically initialized.  You have to assign a
value to `a->name' separately, e.g.,
        a = malloc (sizeof *a);
        a->name = malloc (strlen (data) + 1);

Quote:
> strcpy(a->name, data);

--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
 \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}


Wed, 13 Apr 2005 02:28:21 GMT  
 dynamic char * length in a struct


Quote:
>typedef struct student {
>  struct student *next;
>  char *name;
>} student_t;

>/* skipped */

>/* start of a function */
>char data[30];
>student_t *a;

>scanf(" %s", data);

I'd rather use fgets for this. scanf is difficult to use safely.

Quote:
>/*
> * how to allocate memory for "a"
> * according to the length of data?
> * I do it this way, but the program crashed
> */

>a = (student *) malloc(sizeof(student_t) + strlen(data) + 1);
>strcpy(a->name, data);

Allocate enough space for the struct and the string, and point ''a''
at it

  a = malloc(sizeof *a + strlen(data) + 1);

If the allocation succeeded, point ''a->name'' at the remaining space

  a->name = (char *)(a + 1);

and copy the string data across

  strcpy(a->name, data);

Note that there is no need to cast malloc's return value when
assigning it to a pointer.

-- Mat.



Wed, 13 Apr 2005 02:31:35 GMT  
 dynamic char * length in a struct

Quote:

>  typedef struct student {
>    struct student *next;
>    char *name;
>  } student_t;

>  /* skipped */

>  /* start of a function */
>  char data[30];
>  student_t *a;

>  scanf(" %s", data);

Don't use scanf like that; it doesn't know how long your buffer is, so
if the user enters a word of more than 29 characters, data will
overflow.

Quote:
>  /*
>   * how to allocate memory for "a"
>   * according to the length of data?
>   * I do it this way, but the program crashed
>   */

>  a = (student *) malloc(sizeof(student_t) + strlen(data) + 1);
>  strcpy(a->name, data);

The most straight-forward way to do what you want is something like:
    a = malloc(sizeof *a); /* allocate one student record */
    a->name = malloc(strlen(data) + 1); /* allocate space for the name */
    strcpy(a->name, data); /* copy the name */
Don't forget to always check malloc's return value! If you allocate your
students like this, you will have to call free twice to clean up:
    free(a->name); /* free the name *before* you free the struct */
    free(a);

Your malloc call allocates enough memory for the struct and the string,
so you could also do this:
    a->name = (char *) a + sizeof *a; /* let a->name point past the end
                                         of the struct, into memory that
                                         still belongs to us */
    strcpy(a->name, data);
Then, you would use only one free call:
    free(a); /* free the combined buffer for the struct and the string */
This approach doesn't have a clear benefit, however[0], and it's not
idiomatic, which might confuse readers without good reason.

[0] Actually, it might run faster and reduce malloc arena fragmentation
by allocating larger blocks. But you shouldn't usually be worried about
such things.

Gergo
--
You are confused; but this is your normal state.



Wed, 13 Apr 2005 02:42:46 GMT  
 dynamic char * length in a struct

Quote:

> typedef struct student {
>   struct student *next;
>   char *name;
> } student_t;

> /* skipped */

> /* start of a function */
> char data[30];
> student_t *a;

> scanf(" %s", data);

> /*
>  * how to allocate memory for "a"
>  * according to the length of data?
>  * I do it this way, but the program crashed
>  */

> a = (student *) malloc(sizeof(student_t) + strlen(data) + 1);
> strcpy(a->name, data);

You can't combine the allocations that way.

#include <stdlib.h> /* you don't show this in your snippet, MAKE SURE IT
IS THERE! */

a = malloc (sizeof *a); /* recommended c.l.c way to use malloc() */
/* do error checks */

a->name = malloc (strlen (data) + 1);
/* do error checks */

strcpy (a->name, data);

Brian Rodenborn



Wed, 13 Apr 2005 02:44:12 GMT  
 dynamic char * length in a struct

Quote:
> a = malloc (sizeof *a);
> a->name = malloc (strlen (data) + 1);

i got it working with these two lines!

Quote:
> This isn't safe.  If the user enters more than will fit in
> data[], undefined behavior results.

i also think it is not save, but i can't think of any other way of doing it.
could u please tell me a bit more?

thank you so much!



Wed, 13 Apr 2005 02:53:45 GMT  
 dynamic char * length in a struct

Quote:
> I'd rather use fgets for this. scanf is difficult to use safely.

i tried. i think fgets requires a FILE *. i don't know what to do to get
away with ths FILE *.

Quote:
> a->name = (char *)(a + 1);

it works too! but i don't quite understand what this line means. could you
please explain?

thanks alot!



Wed, 13 Apr 2005 03:05:10 GMT  
 dynamic char * length in a struct

Quote:

> > I'd rather use fgets for this. scanf is difficult to use safely.

> i tried. i think fgets requires a FILE *. i don't know what to do to get
> away with ths FILE *.

To read from the same device as scanf(), use `stdin' as the FILE
* argument to fgets().


Wed, 13 Apr 2005 03:21:56 GMT  
 dynamic char * length in a struct


Quote:
>> I'd rather use fgets for this. scanf is difficult to use safely.

>i tried. i think fgets requires a FILE *. i don't know what to do to get
>away with ths FILE *.

stdin (declared in <stdio.h>) is a suitable FILE * to use here.

Quote:
>> a->name = (char *)(a + 1);

>it works too! but i don't quite understand what this line means. could you
>please explain?

a + 1 produces a pointer to the allocated memory just after the
struct. This is converted to a char * and assigned to a->name, to give
it something to point at.

If you're not confident you understand it I'd suggest using the
simpler "two mallocs" approach given by other posters.

Remember though that two calls to malloc implies two later calls to
free, and you have to be careful in what order you do them

  a = malloc(sizeof *a);
  a->name = malloc(strlen(data) + 1);
  ...
  free(a->name); /* free in reverse order of allocation */
  free(a);

-- Mat.



Wed, 13 Apr 2005 03:32:52 GMT  
 dynamic char * length in a struct

Quote:

> typedef struct student {
>   struct student *next;
>   char *name;

Use  char name[1];

Quote:
> } student_t;

> /* skipped */

> /* start of a function */
> char data[30];
> student_t *a;

> scanf(" %s", data);

> /*
>  * how to allocate memory for "a"
>  * according to the length of data?
>  * I do it this way, but the program crashed
>  */

> a = (student *) malloc(sizeof(student_t) + strlen(data) + 1);

      don't need the +1 anymore

Quote:
> strcpy(a->name, data);

Try real hard to understand why the above (and the other proposed)
solutions work.  You'll need that understanding in the future.


Wed, 13 Apr 2005 03:46:16 GMT  
 dynamic char * length in a struct
thank you so much!
there are so many methods to achieve the same goal ;-)


Wed, 13 Apr 2005 03:42:03 GMT  
 dynamic char * length in a struct

Quote:

> > This isn't safe.  If the user enters more than will fit in
> > data[], undefined behavior results.

> i also think it is not save, but i can't think of any other way of doing it.
> could u please tell me a bit more?

Use the fgets() function, it includes a maximum amount to read.

fgets (data, sizeof data, stdin);

You'll have to decide what to do with leftover characters in the input
buffer if someone does try to enter too much.

Brian Rodenborn



Wed, 13 Apr 2005 03:49:53 GMT  
 dynamic char * length in a struct

Quote:
>Try real hard to understand why the above (and the other proposed)
>solutions work.  You'll need that understanding in the future.

i am trying hard ;-)


Wed, 13 Apr 2005 04:14:16 GMT  
 dynamic char * length in a struct

Quote:


> > typedef struct student {
> >   struct student *next;
> >   char *name;

> Use  char name[1];

> > } student_t;

Please read the FAQ.

2.6:    I came across some code that declared a structure like this:

                struct name {
                        int namelen;
                        char namestr[1];
                };

        and then did some tricky allocation to make the namestr array
        act like it had several elements.  Is this legal or portable?

A:      This technique is popular, although Dennis Ritchie has called it
        "unwarranted chumminess with the C implementation."  An official
        interpretation has deemed that it is not strictly conforming
        with the C Standard, although it does seem to work under all
        known implementations.  (Compilers which check array bounds
        carefully might issue warnings.)

        Another possibility is to declare the variable-size element very
        large, rather than very small; in the case of the above example:

                ...
                char namestr[MAXSIZE];

        where MAXSIZE is larger than any name which will be stored.
        However, it looks like this technique is disallowed by a strict
        interpretation of the Standard as well.  Furthermore, either of
        these "chummy" structures must be used with care, since the
        programmer knows more about their size than the compiler does.
        (In particular, they can generally only be manipulated via
        pointers.)

        C9X will introduce the concept of a "flexible array member",
        which will allow the size of an array to be omitted if it is
        the last member in a structure, thus providing a well-defined
        solution.

        References: Rationale Sec. 3.5.4.2; C9X Sec. 6.5.2.1.

--
"Debugging is twice as hard as writing the code in the first place.
 Therefore, if you write the code as cleverly as possible, you are,
 by definition, not smart enough to debug it."
--Brian Kernighan



Wed, 13 Apr 2005 04:41:47 GMT  
 dynamic char * length in a struct
thanks every one for giving me a lesson.
now i have my struct working + using fgets instead of scanf.


Wed, 13 Apr 2005 05:03:57 GMT  
 
 [ 16 post ]  Go to page: [1] [2]

 Relevant Pages 

1. missing struct vs zero length struct?

2. dynamic linked list + dynamic struct members

3. HELP -> dynamic char** arrays (inside a dynamic struct**)

4. dynamic line length

5. dynamic variable length arrays

6. dynamic string lengths

7. dynamic string lengths to a function

8. String.Format: dynamic lengths

9. Variable length arrays in structs

10. Struct containing an array of unknown length

11. length of struct

12. Indefinite-length array as member of struct: how?

 

 
Powered by phpBB® Forum Software