2D array with different column types / Dumbass can figure out segfault

Discussion in 'C Programming' started by nobrow@gmail.com, Sep 6, 2006.

  1. Guest

    Okay ... Im out of practice. Is it not possible to have a 2D array
    where each column is of a different type, say an int and a struct*? The
    following seg faults for me and I cant figure out what I need to
    change.

    Thanks.

    #include <malloc.h>
    #include <string.h>

    void*** a;
    void f();
    typedef struct
    {
    char* name;
    int idx;
    } A_Type;

    int main()
    {
    f();
    }

    void f()
    {
    int i;
    a = malloc(sizeof(void**) * 2);
    a[0] = malloc(sizeof(int) * 10);
    a[1] = malloc(sizeof(A_Type*) * 10);

    A_Type* tmp;
    for(i = 0; i < 10; i++)
    {
    tmp = malloc(sizeof(A_Type));
    tmp->name = "My Name";
    tmp->idx = i;

    memcpy(a[0], &i, sizeof(int)); /* SEG FAULT HERE */
    a[1] = tmp;
    }
    }
     
    , Sep 6, 2006
    #1
    1. Advertising

  2. Guest

    Konstantin Miller wrote:
    > wrote:
    >
    > > Okay ... Im out of practice. Is it not possible to have a 2D array
    > > where each column is of a different type, say an int and a struct*? The
    > > following seg faults for me and I cant figure out what I need to
    > > change.
    > >
    > > Thanks.
    > >
    > > #include <malloc.h>
    > > #include <string.h>
    > >

    > //void*** a;
    > void **a;
    > > void f();
    > > typedef struct
    > > {
    > > char* name;
    > > int idx;
    > > } A_Type;
    > >
    > > int main()
    > > {
    > > f();
    > > }
    > >
    > > void f()
    > > {
    > > int i;

    > //a = malloc(sizeof(void**) * 2);
    > a = malloc(sizeof(void*) * 2);
    > > a[0] = malloc(sizeof(int) * 10);
    > > a[1] = malloc(sizeof(A_Type*) * 10);
    > >
    > > A_Type* tmp;
    > > for(i = 0; i < 10; i++)
    > > {
    > > tmp = malloc(sizeof(A_Type));
    > > tmp->name = "My Name";
    > > tmp->idx = i;
    > >

    > // memcpy(a[0], &i, sizeof(int)); /* SEG FAULT HERE */
    > // you could do
    > // memcpy(&(a[0]), &i, sizeof(int));
    > // but why not simply:
    > a[0] = i;
    > > a[1] = tmp;
    > > }
    > > }

    >
    > Konstantin


    Hi,

    Thanks but as reasonable as that looks, its not working:

    test.c:34: warning: dereferencing 'void *' pointer
    test.c:34: error: invalid use of void expression
    test.c:35: warning: dereferencing 'void *' pointer
    test.c:35: error: invalid use of void expression

    Lines 34 and 35 being:

    a[0] = i;
    a[1] = tmp;
     
    , Sep 6, 2006
    #2
    1. Advertising

  3. <> wrote in message
    news:...
    > Okay ... Im out of practice. Is it not possible to have a 2D array
    > where each column is of a different type, say an int and a struct*? The
    > following seg faults for me and I cant figure out what I need to
    > change.
    >
    > Thanks.


    It is possible but ugly, difficult, and error-prone. What are you trying to
    do?

    #define NUMINTS 5
    #define NUMDBLS 10

    void ** a;
    a = malloc (2 * sizeof *a);
    a[0] = malloc (NUMINTS * sizeof (int));
    a[1] = malloc (NUMDBLS * sizeof (double));

    // now, to set an int:
    ((int *)a[0])[3] = 42;

    // and to set a double:
    ((double *)a[1])[6] = 3.141592;

    The reason is that a's type is pointer-to-pointer-to-<something>. You can't
    give it a concrete type since it's different in different columns. But you
    can't dereference a pointer-to-<something> without knowing what the
    <something> is. So, at some point in the expression you have to cast the
    pointer to a concrete pointer type in order to dereference it.

    If you have a fixed list of types, and you want an array for each type, why
    don't you do just that?

    int *a = malloc (NUMINTS * sizeof *a);
    double *b = malloc (NUMDBLS * sizeof *b);

    Or, alternatively, you could declare a struct:

    struct mystruct {
    int *iarray;
    double *darray;
    };

    struct mystuct a;
    a.iarray = malloc (NUMINTS * sizeof *a.iarray);
    a.darray = malloc (NUMINTS * sizeof *a.darray);

    Philip
     
    Philip Potter, Sep 6, 2006
    #3
  4. Guest

    Konstantin Miller wrote:
    > wrote:
    >
    > >
    > > Konstantin Miller wrote:
    > >> wrote:
    > >>
    > >> > Okay ... Im out of practice. Is it not possible to have a 2D array
    > >> > where each column is of a different type, say an int and a struct*? The
    > >> > following seg faults for me and I cant figure out what I need to
    > >> > change.
    > >> >
    > >> > Thanks.
    > >> >
    > >> > #include <malloc.h>
    > >> > #include <string.h>
    > >> >
    > >> //void*** a;
    > >> void **a;
    > >> > void f();
    > >> > typedef struct
    > >> > {
    > >> > char* name;
    > >> > int idx;
    > >> > } A_Type;
    > >> >
    > >> > int main()
    > >> > {
    > >> > f();
    > >> > }
    > >> >
    > >> > void f()
    > >> > {
    > >> > int i;
    > >> //a = malloc(sizeof(void**) * 2);
    > >> a = malloc(sizeof(void*) * 2);
    > >> > a[0] = malloc(sizeof(int) * 10);
    > >> > a[1] = malloc(sizeof(A_Type*) * 10);
    > >> >
    > >> > A_Type* tmp;
    > >> > for(i = 0; i < 10; i++)
    > >> > {
    > >> > tmp = malloc(sizeof(A_Type));
    > >> > tmp->name = "My Name";
    > >> > tmp->idx = i;
    > >> >
    > >> // memcpy(a[0], &i, sizeof(int)); /* SEG FAULT HERE */
    > >> // you could do
    > >> // memcpy(&(a[0]), &i, sizeof(int));
    > >> // but why not simply:
    > >> a[0] = i;
    > >> > a[1] = tmp;
    > >> > }
    > >> > }
    > >>
    > >> Konstantin

    > >
    > > Hi,
    > >
    > > Thanks but as reasonable as that looks, its not working:
    > >
    > > test.c:34: warning: dereferencing 'void *' pointer
    > > test.c:34: error: invalid use of void expression
    > > test.c:35: warning: dereferencing 'void *' pointer
    > > test.c:35: error: invalid use of void expression
    > >
    > > Lines 34 and 35 being:
    > >
    > > a[0] = i;
    > > a[1] = tmp;

    >
    > Hi!
    >
    > That's right, you can not dereference a void pointer!
    > Change those lines to
    >
    > ((int*)a[0]) = i;
    > ((A_Type**)a[1]) = tmp;
    >
    > This must work!
    >
    > Konstantin


    Lovely stuff. Thanks for your patience and your help.
     
    , Sep 6, 2006
    #4
  5. wrote:

    > Okay ... Im out of practice. Is it not possible to have a 2D array
    > where each column is of a different type, say an int and a struct*? The
    > following seg faults for me and I cant figure out what I need to
    > change.
    >
    > Thanks.
    >
    > #include <malloc.h>
    > #include <string.h>
    >

    //void*** a;
    void **a;
    > void f();
    > typedef struct
    > {
    > char* name;
    > int idx;
    > } A_Type;
    >
    > int main()
    > {
    > f();
    > }
    >
    > void f()
    > {
    > int i;

    //a = malloc(sizeof(void**) * 2);
    a = malloc(sizeof(void*) * 2);
    > a[0] = malloc(sizeof(int) * 10);
    > a[1] = malloc(sizeof(A_Type*) * 10);
    >
    > A_Type* tmp;
    > for(i = 0; i < 10; i++)
    > {
    > tmp = malloc(sizeof(A_Type));
    > tmp->name = "My Name";
    > tmp->idx = i;
    >
    > memcpy(a[0], &i, sizeof(int)); /* SEG FAULT HERE */
    > a[1] = tmp;
    > }
    > }


    Konstantin
     
    Konstantin Miller, Sep 6, 2006
    #5
  6. wrote:

    > Okay ... Im out of practice. Is it not possible to have a 2D array
    > where each column is of a different type, say an int and a struct*? The
    > following seg faults for me and I cant figure out what I need to
    > change.
    >
    > Thanks.
    >
    > #include <malloc.h>
    > #include <string.h>
    >

    //void*** a;
    void **a;
    > void f();
    > typedef struct
    > {
    > char* name;
    > int idx;
    > } A_Type;
    >
    > int main()
    > {
    > f();
    > }
    >
    > void f()
    > {
    > int i;

    //a = malloc(sizeof(void**) * 2);
    a = malloc(sizeof(void*) * 2);
    > a[0] = malloc(sizeof(int) * 10);
    > a[1] = malloc(sizeof(A_Type*) * 10);
    >
    > A_Type* tmp;
    > for(i = 0; i < 10; i++)
    > {
    > tmp = malloc(sizeof(A_Type));
    > tmp->name = "My Name";
    > tmp->idx = i;
    >

    // memcpy(a[0], &i, sizeof(int)); /* SEG FAULT HERE */
    // you could do
    // memcpy(&(a[0]), &i, sizeof(int));
    // but why not simply:
    a[0] = i;
    > a[1] = tmp;
    > }
    > }


    Konstantin
     
    Konstantin Miller, Sep 6, 2006
    #6
  7. wrote:

    >
    > Konstantin Miller wrote:
    >> wrote:
    >>
    >> > Okay ... Im out of practice. Is it not possible to have a 2D array
    >> > where each column is of a different type, say an int and a struct*? The
    >> > following seg faults for me and I cant figure out what I need to
    >> > change.
    >> >
    >> > Thanks.
    >> >
    >> > #include <malloc.h>
    >> > #include <string.h>
    >> >

    >> //void*** a;
    >> void **a;
    >> > void f();
    >> > typedef struct
    >> > {
    >> > char* name;
    >> > int idx;
    >> > } A_Type;
    >> >
    >> > int main()
    >> > {
    >> > f();
    >> > }
    >> >
    >> > void f()
    >> > {
    >> > int i;

    >> //a = malloc(sizeof(void**) * 2);
    >> a = malloc(sizeof(void*) * 2);
    >> > a[0] = malloc(sizeof(int) * 10);
    >> > a[1] = malloc(sizeof(A_Type*) * 10);
    >> >
    >> > A_Type* tmp;
    >> > for(i = 0; i < 10; i++)
    >> > {
    >> > tmp = malloc(sizeof(A_Type));
    >> > tmp->name = "My Name";
    >> > tmp->idx = i;
    >> >

    >> // memcpy(a[0], &i, sizeof(int)); /* SEG FAULT HERE */
    >> // you could do
    >> // memcpy(&(a[0]), &i, sizeof(int));
    >> // but why not simply:
    >> a[0] = i;
    >> > a[1] = tmp;
    >> > }
    >> > }

    >>
    >> Konstantin

    >
    > Hi,
    >
    > Thanks but as reasonable as that looks, its not working:
    >
    > test.c:34: warning: dereferencing 'void *' pointer
    > test.c:34: error: invalid use of void expression
    > test.c:35: warning: dereferencing 'void *' pointer
    > test.c:35: error: invalid use of void expression
    >
    > Lines 34 and 35 being:
    >
    > a[0] = i;
    > a[1] = tmp;


    Hi!

    That's right, you can not dereference a void pointer!
    Change those lines to

    ((int*)a[0]) = i;
    ((A_Type**)a[1]) = tmp;

    This must work!

    Konstantin
     
    Konstantin Miller, Sep 6, 2006
    #7
  8. On 6 Sep 2006 03:26:45 -0700, wrote:

    >Okay ... Im out of practice. Is it not possible to have a 2D array
    >where each column is of a different type, say an int and a struct*? The
    >following seg faults for me and I cant figure out what I need to
    >change.


    snip code

    It would be much simpler if you did it with an array of struct. Each
    element of the array would be a row while each member of the struct
    would be a column. You could have as many columns as you want, each
    with an independent type.


    Remove del for email
     
    Barry Schwarz, Sep 7, 2006
    #8
  9. Groovy hepcat was jivin' on 6 Sep 2006 03:26:45 -0700
    in comp.lang.c.
    2D array with different column types / Dumbass can figure out
    segfault's a cool scene! Dig it!

    >Okay ... Im out of practice. Is it not possible to have a 2D array
    >where each column is of a different type, say an int and a struct*? The


    Well, you could use a union, I suppose. But it looks like what you
    really need is a 1D array of struct. The first member of this struct
    should be your int, and the second member your other struct. Something
    like this:

    #include <stdlib.h>

    #define NUM 10

    typedef struct
    {
    char* name;
    int idx;
    } A_Type;

    struct allinfo
    {
    int foo;
    A_Type bar;
    };

    int main(void)
    {
    struct allinfo a[NUM];
    int i;

    for(i = 0; i < NUM; i++)
    {
    a.foo = i;
    a.bar.name = "My Name";
    a.bar.idx = i;
    }

    return 0;
    }

    >following seg faults for me and I cant figure out what I need to
    >change.
    >
    >Thanks.
    >
    >#include <malloc.h>


    No such header in standard C. What you need is this:

    #include <stdlib.h>

    >#include <string.h>
    >
    >void*** a;


    Why is this defined here, at file scope, instead of within a
    function? There's no reason I can see to define this here. It would be
    better defined in f().

    >void f();


    Prototypes have been around since 1989. And they're much better than
    the alternative. There's no reason to use K&R style function
    declarations anymore.

    void f(void);

    >typedef struct
    >{
    > char* name;
    > int idx;
    >} A_Type;
    >
    >int main()


    int main(void)
    >{
    > f();


    Why just have main() call f()? Seems rather pointless to me. It
    would probably be better to put the guts of f() in main() instead. But
    that's up to you.
    You're not returning anything? You have an int function but you
    don't return an int. That's not only not recommended, but actually
    illegal in C90. Go on; return something. It's not hard.

    return 0;
    >}
    >
    >void f()


    void f(void)
    >{
    > int i;
    > a = malloc(sizeof(void**) * 2);
    > a[0] = malloc(sizeof(int) * 10);


    Wrong type. Since a is a void***, a[0] is a void**. *(a[0]) is,
    therefore, a void*. But you are allocating enough space for 10 ints,
    not 10 void*s.

    > a[1] = malloc(sizeof(A_Type*) * 10);


    Wrong type. Since a is a void***, a[1] is a void**. *(a[1]) is,
    therefore, a void*. But you are allocating enough space for 10
    A_Type*s, not 10 void*s.
    You have three malloc() calls here, none of which are checked for
    failure. This is a very bad situation. malloc() can fail for unforseen
    reasons; and when it does, you must take appropriate action to ensure
    you don't dereference a null pointer.
    Since the number of elements is known beforehand, why allocate
    memory dynamically? An array would be better, I think.

    > A_Type* tmp;
    > for(i = 0; i < 10; i++)
    > {
    > tmp = malloc(sizeof(A_Type));


    Another unchecked malloc() call. Bad!

    > tmp->name = "My Name";
    > tmp->idx = i;
    >
    > memcpy(a[0], &i, sizeof(int)); /* SEG FAULT HERE */
    > a[1] = tmp;
    > }
    >}


    Your use of void*** is flawed, I'm afraid. There are basically three
    ways I can see around this: the way I have shown above, using another
    struct; correcting what you are actually trying to do, using void* and
    allocating a pointer to int or pointer to A_Type, as needed, and
    assigning that to the void*; and using a union containing an int and
    an A_Type, and simply using a 2D array of these. There may be other
    ways I haven't thought of, but these should be enough. Of course, I
    very much favour the first of those solutions. The other two are very
    messy.

    --

    Dig the even newer still, yet more improved, sig!

    http://alphalink.com.au/~phaywood/
    "Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
    I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
     
    Peter Shaggy Haywood, Sep 10, 2006
    #9
    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. Child
    Replies:
    3
    Views:
    337
    John Timney \(Microsoft MVP\)
    Aug 8, 2003
  2. James D Carroll

    Here's a dumbass question

    James D Carroll, Jun 19, 2004, in forum: Java
    Replies:
    9
    Views:
    412
    Chris Smith
    Jun 21, 2004
  3. Andrey Vul
    Replies:
    8
    Views:
    714
    Richard Bos
    Jul 30, 2010
  4. Replies:
    7
    Views:
    374
    Dan Rogers
    Dec 1, 2004
  5. Ryan Davis
    Replies:
    0
    Views:
    146
    Ryan Davis
    Oct 23, 2008
Loading...

Share This Page