multi-type

A

andre.koskamp

Hello,

Is there a possibility to initiate an array with more types, say int's
and char's? I think it is possible to dynamically make a multi
dimensional array, and then typecast the return value of malloc()
function:

int **array = (int **)malloc(ROWS * sizeof(int *));
for(i = 0; i < ROWS; i++)
array[0] = (int *)malloc(sizeof(int));
array[1] = (char *)malloc(sizeof(char));
array[2] = (float *)malloc(sizeof(float));
etc.

Is this a correct way to do this?
If not could someone explain?

Thanks for your advises.
 
S

Suman

Hello,

Is there a possibility to initiate an array with more types, say int's
and char's? I think it is possible to dynamically make a multi
dimensional array, and then typecast the return value of malloc()
- is not a good thing to do in general.
function:

int **array = (int **)malloc(ROWS * sizeof(int *));
for(i = 0; i < ROWS; i++)
array[0] = (int *)malloc(sizeof(int));
array[1] = (char *)malloc(sizeof(char));
array[2] = (float *)malloc(sizeof(float));
etc.
BTW: Did you actually compile this? What did your `C' compiler say?
Is this a correct way to do this? No.
If not could someone explain?
array is still a pointer to int, so can't just do what you are
doing.
Maybe you can make an array of
unions and make it work the way you want.
 
A

andre.koskamp

My c compiler didn't say a thing,but as you say it isn't working.
Unions allocate space for the biggest type in the union, that is why I
don't want to use unions.

Maybe someone can help me with another question:

NUMBER_OF_CHARS 20

Test = (char**) malloc(ROWS * sizeof(char*));

for(i=0 ; i<ROWS ; i++)
{
Test = (char*) malloc(KOLUMS * NUMBER_OF_CHARS * sizeof(char));
}

Test[0] = "test1";
Test[0][20] = "test2";
Test[0][40] = "test3";

When I now read the data in Test starting at Test[0][0] it contains
"test1",which is correct I think, but "test2" begins at Test[0][8]. I
think it should start at Test[0][20], am I wrong?

Has someone a explanation for this?

Thanks for your help,

André
 
A

Abhi

what about creating a array of union of following type

typedef union{
char *cp;
int *ip;
float *fp;
} PTR;

PTR *ptr;

Now you can have rows of different data types without consuming
additional memory.
Let me know if this works fine...

Regards,
-Abhishikt
 
A

Abhi

I feel void ** is a better way to achieve this. But a lot of care must
be taken while programming with such variables, as we should not
accidently use Nth row as integers, while it is of characters. So
ideally we should be avoiding such kind of stuff, instead we can have
different variables char** and int ** ;-))

Regards,
-Abhishikt
 
L

Lawrence Kirby

Hello,

Is there a possibility to initiate an array with more types, say int's
and char's?

No, all of the elements of an array have the same type, always.
I think it is possible to dynamically make a multi
dimensional array, and then typecast the return value of malloc()
function:

int **array = (int **)malloc(ROWS * sizeof(int *));
for(i = 0; i < ROWS; i++)
array[0] = (int *)malloc(sizeof(int));
array[1] = (char *)malloc(sizeof(char));

Here you cast the return value of malloc() to char * then try to assign
that char * to an object of type int * which is invalid.
array[2] = (float *)malloc(sizeof(float));
etc.

Is this a correct way to do this?
If not could someone explain?

C is a statically typed language, what you see is what you get. The
variable array above has type pointer to pointer to int, i.e. what it can
point at are object of type pointer to int. That's it.

You might get closer to what you want using an array of unions. But it is
still up to you to select the correct union member when accessing the
elements, this won't magically happen for you.

Lawrence
 
L

Lawrence Kirby

My c compiler didn't say a thing,but as you say it isn't working.
Unions allocate space for the biggest type in the union, that is why I
don't want to use unions.

If each row has elements all of the same type then you could use a union
of pointer types, or perhaps just void *. It is still up to you to select
the correct union member of convert the void * pointer type to the
appropriate type for dereferencing though.
Maybe someone can help me with another question:

NUMBER_OF_CHARS 20

Test = (char**) malloc(ROWS * sizeof(char*));

Note that you don't need to cast the return value of malloc() and many
consider it a bad thing to do because it can obscure bugs, such as failing
to #include <stdlib.h> to provide a proper declaration for malloc(). A
good wayu to write this is

Test = malloc(ROWS * sizeof *Test);

Also don't forget to test the return value of malloc() for failure.
for(i=0 ; i<ROWS ; i++)
{
Test = (char*) malloc(KOLUMS * NUMBER_OF_CHARS * sizeof(char));
}
}
Test[0] = "test1";


You've created a memory leak. Test[0] was pointing at malloc'd memory
(assuming malloc didn't return null). You've now set it to point at a
string literal i.e. it no longer points at the malloc'd memory and that
remains allocated but no longer accesible i.e. a memory leak.
Test[0][20] = "test2";
Test[0][40] = "test3";

These are invalid C, you are trying to assign a char * value to a char.
A C compiler is required to complain about this.
When I now read the data in Test starting at Test[0][0] it contains
"test1",which is correct I think, but "test2" begins at Test[0][8]. I
think it should start at Test[0][20], am I wrong?

Since the code is invalid there's no "should" about it. What is the value
of KOLUMNS? If it is at least 2 then you might be looking for:

strcpy(&Test[0][20], "test2");
strcpy(&Test[0][40], "test3");

strcpy() copies strings, = as above just copies pointers, so you need a
pointer object to put the value in.

Lawrence
 
S

Suman

My c compiler didn't say a thing,but as you say it isn't working.
Unions allocate space for the biggest type in the union, that is why I
don't want to use unions.
Suit yourself.
Maybe someone can help me with another question:

NUMBER_OF_CHARS 20
A proper #define would've been nice.
Test = (char**) malloc(ROWS * sizeof(char*));
Don't do that.I am being assertive now, but that cast masks off
warnings and/or possible bugs.
for(i=0 ; i<ROWS ; i++) Where is the defintion of ROW?
{
Test = (char*) malloc(KOLUMS * NUMBER_OF_CHARS * sizeof(char));

....and KOLUMS?And sizeof(char) == 1, always, come hell or high water,
so you can skip it.
}

Test[0] = "test1"; Why are you doing this?
Test[0][20] = "test2";
Test[0][40] = "test3";
Just not done!Test[0][x] is of type char, whereas "test?" is a string
literal
containing 6 characters(yes including the '\0'), and they are *not*
compatible in the sense you can make that assignment.Did you compile
this, and did you not get any diagnostic?
When I now read the data in Test starting at Test[0][0] it contains
"test1",which is correct I think, but "test2" begins at Test[0][8]. I
think it should start at Test[0][20], am I wrong?

Has someone a explanation for this?
Can you post some code that you have actually written, maybe we can
help you better?
 
S

Suman

Abhi said:
I feel void ** is a better way to achieve this. But a lot of care must
be taken while programming with such variables, as we should not
accidently use Nth row as integers, while it is of characters. So
ideally we should be avoiding such kind of stuff, instead we can have
different variables char** and int ** ;-))
Arguably. Can you enlighten us?
 
A

Abhi

My point is that if one needs (for e.g.) 2 char rows, 2 int rows and 2
float rows in that array of pointers. (as andre is mentioning). We can
achieve it using void ** and have 6 void * and use it.
It is better to use a char**, int ** and float**. It will take just 8
bytes extra memory (in 32-bit architecture). This can make sure
complexity is low and also human (programmer) error can be caught in
compilation stage. :)

Regards,
-Abhishikt
 
A

andre.koskamp

Creating a array of the union-type works fine I think. I tried it just
for a few values but everything works. I hope I can use this, thanks
for al your help
 
L

Lawrence Kirby

My point is that if one needs (for e.g.) 2 char rows, 2 int rows and 2
float rows in that array of pointers. (as andre is mentioning). We can
achieve it using void ** and have 6 void * and use it.
It is better to use a char**, int ** and float**. It will take just 8
bytes extra memory (in 32-bit architecture).

I'm not sure what you are saying here. While it is certainly true that
char **, int ** and float ** (and indeed char *, int * and float *) aren't
guaranteed to be the same size, they are on most 32 bit implementations
out there.
This can make sure
complexity is low and also human (programmer) error can be caught in
compilation stage. :)

Of course it all depends on HOW you use void *. You still need some way to
determine what type of object/array of objects each void * pointer is
pointing to.

Lawrence
 

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

Forum statistics

Threads
474,166
Messages
2,570,907
Members
47,447
Latest member
TamiLai26

Latest Threads

Top