Allocating an array of char* - newbie

Discussion in 'C Programming' started by john, Oct 26, 2004.

  1. john

    john Guest

    Hello,
    I wrote thsi small program ; I am quite a newbie in this.

    #include <stdio.h>
    #include <stdlib.h>


    typedef struct argsArray
    {

    char* ip_addresses[];
    int no_of_addresses;
    } argsArray;


    int main()
    {
    argsArray* argsArrayPtr = (argsArray*)malloc(sizeof (argsArray));
    argsArrayPtr->no_of_addresses = 3;
    argsArrayPtr->ip_addresses[0]="10.0.0.0";
    argsArrayPtr->ip_addresses[1]="10.0.0.1";

    printf("no_of_addresses %d\n",argsArrayPtr->no_of_addresses);

    printf("argsArrayPtr->ip_addresses[0] = %s\n",argsArrayPtr->ip_addresses[0]);
    printf("argsArrayPtr->ip_addresses[1] = %s\n",argsArrayPtr->ip_addresses[1]);

    }

    this program prints:

    no_of_addresses 134514264
    argsArrayPtr->ip_addresses[0] = 10.0.0.0
    argsArrayPtr->ip_addresses[1] = 10.0.0.1

    where no_of_addresses should be 3;
    It is obviously a matter of performing malloc() to the ip_addresses[] array;
    but what should I exactly do it ? I do not know the sizes of the IP addresses :
    they can vary from 7 to 15 characters length .Moreover, I do not know the
    number of elements (ip addresses) in that array ; it is filled in run time
    from some file. (I do have an upper bound).


    regards,
    John
     
    john, Oct 26, 2004
    #1
    1. Advertising

  2. john

    -berlin.de Guest

    john <> wrote:
    > I wrote thsi small program ; I am quite a newbie in this.


    > #include <stdio.h>
    > #include <stdlib.h>



    > typedef struct argsArray
    > {
    > char* ip_addresses[];


    That's not valid C, you can't create an array of (char pointers) of
    indeterminate size. What you will need here is a pointer to pointer
    to char and, once you know how many pointers you need, you must
    allocate enough for them. So make that

    char **ip_addresses;

    > int no_of_addresses;
    > } argsArray;
    >


    > int main()
    > {
    > argsArray* argsArrayPtr = (argsArray*)malloc(sizeof (argsArray));


    It usually doesn't make too much sense to cast the return value of
    malloc(). The conversion is done automatically for you and the cast
    will keep the compiler from warning you if you forget to include
    <stdlib.h> where malloc() is declared. Furthermore, you should make
    it a habit to always check the return value - if malloc() fails it
    returns a NULL pointer. But if you only need one of these structures
    it probably would make more sense here to use a real structure here
    instead of using a pointer and then allocating memory for it...

    > argsArrayPtr->no_of_addresses = 3;
    > argsArrayPtr->ip_addresses[0]="10.0.0.0";
    > argsArrayPtr->ip_addresses[1]="10.0.0.1";


    Before you can do that you need to allocate memory for the pointers.
    Do that e.g. by

    if ( ( argsArrayPtr->ip_addresses =
    malloc( 2 * sizeof *argsArrayPtr->ip_addresses ) )
    == NULL ) {
    fprintf( stderr, "Running out of memory\n" );
    exit( EXIT_FAILURE );
    }

    If you want not just to assign some addresses of literal strings
    (like you do in your example code) but copy strings you also will
    have to allocate memory for the strings themselves and assign that
    to the char pointers you got from the previous allocation.

    > printf("no_of_addresses %d\n",argsArrayPtr->no_of_addresses);
    >
    > printf("argsArrayPtr->ip_addresses[0] = %s\n",argsArrayPtr->ip_addresses[0]);
    > printf("argsArrayPtr->ip_addresses[1] = %s\n",argsArrayPtr->ip_addresses[1]);


    > }
    >
    > this program prints:


    > no_of_addresses 134514264
    > argsArrayPtr->ip_addresses[0] = 10.0.0.0
    > argsArrayPtr->ip_addresses[1] = 10.0.0.1


    > where no_of_addresses should be 3;
    > It is obviously a matter of performing malloc() to the ip_addresses[] array;
    > but what should I exactly do it ? I do not know the sizes of the IP
    > addresses: they can vary from 7 to 15 characters length.


    Well, first thing you need to do is allocate memory for the pointers
    to the strings. Then you have to allocate memory for the strings. If
    you don't know how long a string is going to be but have an upper bound
    allocate enough memory for the worst case (and don't forget about the
    trailing '\0' character!) and, when you find that this was too pessi-
    mistic, i.e. you don't need all of it, use realloc() to reduce the size
    of the allocated memory.

    > Moreover, I do not know the number of elements (ip addresses) in that
    > array ; it is filled in run time from some file. (I do have an upper
    > bound).


    Again, if you have an upper bound you can always start with the worst
    case scenario and later get rid of the memory you don't need by using
    realloc(). But you can also employ a different strategy: start with a
    guess and, if that turns out to be too optimistic, increase the size
    by also using realloc(). In the simplest case you could start of with
    a pointer for just a single string and, if you find that there's one
    more, just increase the size and repeat until you got all of them.
    Unless this part of the program is used extremely often the impact one
    the performance probably is going to be neglectable. Or start with a
    guess, and if that turns out to be too small, double the size and
    continue and repeat if necessary. - and when you're finished get rid
    of the superfluous memory by a final call of realloc().

    Here's some C code mixed with pseudo code using the simplest method,
    i.e. increasing the array of char pointers each time you find that
    there's still one more IP address to store:

    #define MAX_IP_LENGTH 16

    int ip_count = 0;

    argsArrayPtr->ip_addresses = NULL;

    do {
    determine if there's another IP address
    if ( no_more_IP_addresses )
    break;

    argsArrayPtr->ip_addresses =
    realloc( argsArrayPtr->ip_addresses,
    ( ip_count + 1 ) * sizeof *argsArrayPtr->ip_addresses );

    if ( argsArrayPtr->ip_addresses == NULL ) {
    fprintf( stderr, "Running out of memory\n" );
    exit( EXIT_FAILURE );
    }

    argsArrayPtr->ip_addresses[ ip_count ] = malloc( MAX_IP_LENGTH );

    if ( argsArrayPtr->ip_addresses[ ip_count ] == NULL ) {
    fprintf( stderr, "Running out of memory\n" );
    exit( EXIT_FAILURE );
    }

    store address of new IP address string into 'the_new_ip_address';
    strcpy( argsArrayPtr->ip_addresses[ ip_count ], the_new_ip_address );

    argsArrayPtr->ip_addresses[ ip_count++ ] =
    realloc( argsArrayPtr->ip_addresses[ ip_count ],
    strlen( the_new_ip_address ) + 1 );
    }

    If you want to write that in a way where you are able to recover from
    the case that you run out of memory instead of just exit()ing make sure
    you store the pointer with the address of the memory you already own
    before you call realloc(), otherwise you won't be able to deallocate
    it anymore.
    Regards, Jens
    --
    \ Jens Thoms Toerring ___ -berlin.de
    \__________________________ http://www.toerring.de
     
    -berlin.de, Oct 26, 2004
    #2
    1. Advertising

  3. john

    Neil Kurzman Guest

    john wrote:

    > Hello,
    > I wrote thsi small program ; I am quite a newbie in this.
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    >
    > typedef struct argsArray
    > {
    >
    > char* ip_addresses[];
    > int no_of_addresses;
    > } argsArray;
    >
    >
    > int main()
    > {
    > argsArray* argsArrayPtr = (argsArray*)malloc(sizeof (argsArray));
    > argsArrayPtr->no_of_addresses = 3;
    > argsArrayPtr->ip_addresses[0]="10.0.0.0";
    > argsArrayPtr->ip_addresses[1]="10.0.0.1";
    >
    > printf("no_of_addresses %d\n",argsArrayPtr->no_of_addresses);
    >
    > printf("argsArrayPtr->ip_addresses[0] = %s\n",argsArrayPtr->ip_addresses[0]);
    > printf("argsArrayPtr->ip_addresses[1] = %s\n",argsArrayPtr->ip_addresses[1]);
    >
    > }
    >
    > this program prints:
    >
    > no_of_addresses 134514264
    > argsArrayPtr->ip_addresses[0] = 10.0.0.0
    > argsArrayPtr->ip_addresses[1] = 10.0.0.1
    >
    > where no_of_addresses should be 3;
    > It is obviously a matter of performing malloc() to the ip_addresses[] array;
    > but what should I exactly do it ? I do not know the sizes of the IP addresses :
    > they can vary from 7 to 15 characters length .Moreover, I do not know the
    > number of elements (ip addresses) in that array ; it is filled in run time
    > from some file. (I do have an upper bound).
    >
    > regards,
    > John


    You do realize that standard IP address can be stored as 4 bytes
    ie
    byte[0] =10
    byte[1] =0
    byte[2] =0
    byte[3] =0

    people use 10.0.0.1 the computer uses 0x0A000000
     
    Neil Kurzman, Oct 27, 2004
    #3
    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.

Share This Page