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

N

nobrow

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;
}
}
 
N

nobrow

Konstantin said:
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;
 
P

Philip Potter

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
 
N

nobrow

Konstantin said:
Konstantin said:
(e-mail address removed) 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.
 
K

Konstantin Miller

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
 
K

Konstantin Miller

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
 
K

Konstantin Miller

Konstantin said:
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
 
B

Barry Schwarz

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
 
P

Peter Shaggy Haywood

Groovy hepcat (e-mail address removed) 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 said:
#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)

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"?
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
44,999
Latest member
MakersCBDGummiesReview

Latest Threads

Top