Connecting Tech Pros Worldwide Help | Site Map

Adress arithmetic and dynamic arrays

Alfonso Morra
Guest
 
Posts: n/a
#1: Nov 15 '05
Hi,

I'm trying to write a simple generic container. I have the ff:

typedef union {
long int_val ;
char* string_val ;
double dbl_val ;
void* vptr_val ;
}Element ;

I want to be able to store vars of type Element in a dynamic (i.e.
resizable) array . I tried the ff:


#define MAX_NUM 3

int main(int argc, char* argv[]) {

Element* data ;
int i ;

for (i=0;i< MAX_NUM; i++) {
data++ = (Element*)calloc(1, sizeof(int)) ;
*(data) = i ;
}

for (i=0;i< MAX_NUM; i++)
printf("Element %d has value : %d", i,*(data[i])) ;

for (i=0;i< MAX_NUM; i++)
free(data[i]) ;
}

It is obviously wrong (illegal indirection etc). This is schoolboy stuff
and embarassingly, I've forgotten how to fix it! (using C++ and STL
libraries for too long!).

Any help or pointers (pun intended) much appreciated

Christopher Benson-Manica
Guest
 
Posts: n/a
#2: Nov 15 '05

re: Adress arithmetic and dynamic arrays


Alfonso Morra <sweet-science@the-ring.com> wrote:
[color=blue]
> typedef union {
> long int_val ;
> char* string_val ;
> double dbl_val ;
> void* vptr_val ;
> }Element ;[/color]

Nothing wrong here...
[color=blue]
> #define MAX_NUM 3[/color]
[color=blue]
> int main(int argc, char* argv[]) {[/color]
[color=blue]
> Element* data ;
> int i ;[/color]
[color=blue]
> for (i=0;i< MAX_NUM; i++) {
> data++ = (Element*)calloc(1, sizeof(int)) ;[/color]

It's neither necessary nor advisable to cast the return value of
*alloc in this language (forgivable since you've become used to doing
it in C++, from the sound of it).
[color=blue]
> *(data) = i ;
> }[/color]

What you really wanted was something like

/* Allocate enough space for MAX_NUM Elements */

data=malloc( MAX_NUM * sizeof *data ); /* check for NULL */
for( i=0; i < MAX_NUM; i++ ) {
data[i].int_val=i;
}

sizeof Element is by no means guaranteed to be sizeof int; an Element
is at least as large as its largest member, which in this case is
most likely not the int_val. Notice also that you must assign to the
int_val member of the union.
[color=blue]
> for (i=0;i< MAX_NUM; i++)
> printf("Element %d has value : %d", i,*(data[i])) ;[/color]

printf( "Element %d has value: %ld\n", i, data[i].int_val );
[color=blue]
> for (i=0;i< MAX_NUM; i++)
> free(data[i]) ;[/color]

free( data );
[color=blue]
> }[/color]

I hope that helped.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Christopher Benson-Manica
Guest
 
Posts: n/a
#3: Nov 15 '05

re: Adress arithmetic and dynamic arrays


Christopher Benson-Manica <ataru@nospam.cyberspace.org> wrote:
[color=blue]
> Alfonso Morra <sweet-science@the-ring.com> wrote:[/color]
[color=blue]
> Nothing wrong here...[/color]
[color=blue][color=green]
> > data++ = (Element*)calloc(1, sizeof(int)) ;[/color][/color]
[color=blue][color=green]
> > printf("Element %d has value : %d", i,*(data[i])) ;[/color][/color]

I meant to add that you also neglected to include (perhaps not in your
real code) <stdio.h> and <stdlib.h>, which is as big a problem as it
would have been in C++.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Alfonso Morra
Guest
 
Posts: n/a
#4: Nov 15 '05

re: Adress arithmetic and dynamic arrays




Christopher Benson-Manica wrote:
[color=blue]
> Alfonso Morra <sweet-science@the-ring.com> wrote:
>
>[color=green]
>>typedef union {
>> long int_val ;
>> char* string_val ;
>> double dbl_val ;
>> void* vptr_val ;
>>}Element ;[/color]
>
>
> Nothing wrong here...
>
>[color=green]
>>#define MAX_NUM 3[/color]
>
>[color=green]
>>int main(int argc, char* argv[]) {[/color]
>
>[color=green]
>> Element* data ;
>> int i ;[/color]
>
>[color=green]
>> for (i=0;i< MAX_NUM; i++) {
>> data++ = (Element*)calloc(1, sizeof(int)) ;[/color]
>
>
> It's neither necessary nor advisable to cast the return value of
> *alloc in this language (forgivable since you've become used to doing
> it in C++, from the sound of it).
>
>[color=green]
>> *(data) = i ;
>> }[/color]
>
>
> What you really wanted was something like
>
> /* Allocate enough space for MAX_NUM Elements */
>
> data=malloc( MAX_NUM * sizeof *data ); /* check for NULL */
> for( i=0; i < MAX_NUM; i++ ) {
> data[i].int_val=i;
> }
>
> sizeof Element is by no means guaranteed to be sizeof int; an Element
> is at least as large as its largest member, which in this case is
> most likely not the int_val. Notice also that you must assign to the
> int_val member of the union.
>
>[color=green]
>> for (i=0;i< MAX_NUM; i++)
>> printf("Element %d has value : %d", i,*(data[i])) ;[/color]
>
>
> printf( "Element %d has value: %ld\n", i, data[i].int_val );
>
>[color=green]
>> for (i=0;i< MAX_NUM; i++)
>> free(data[i]) ;[/color]
>
>
> free( data );
>
>[color=green]
>>}[/color]
>
>
> I hope that helped.
>[/color]
Thanks Christopher

Barry Schwarz
Guest
 
Posts: n/a
#5: Nov 15 '05

re: Adress arithmetic and dynamic arrays


On Fri, 16 Sep 2005 16:17:13 +0000 (UTC), Alfonso Morra
<sweet-science@the-ring.com> wrote:
[color=blue]
>Hi,
>
>I'm trying to write a simple generic container. I have the ff:
>
>typedef union {
> long int_val ;
> char* string_val ;
> double dbl_val ;
> void* vptr_val ;
>}Element ;
>
>I want to be able to store vars of type Element in a dynamic (i.e.
>resizable) array . I tried the ff:
>
>
>#define MAX_NUM 3
>
>int main(int argc, char* argv[]) {
>
> Element* data ;[/color]

At this point, data is uninitialized.
[color=blue]
> int i ;
>
> for (i=0;i< MAX_NUM; i++) {
> data++ = (Element*)calloc(1, sizeof(int)) ;[/color]

First a syntax error. data++ is not a modifiable lvalue and so may
not appear on the left of an assignment.

If it could, you would be invoking undefined behavior. Since data is
uninitialized, you cannot increment it.

And finally a "style" issue. Casting the return from calloc rarely
helps but it does cause the compiler to suppress some important
diagnostics if you forget to place a prototype in scope.
[color=blue]
> *(data) = i ;[/color]

Another syntax error. data is a pointer to union. *data is an actual
union. i is an int. You cannot assign an int to a union. You must
assign the value to one of the members of the union, in this case
either int_val or dbl_val.
[color=blue]
> }
>
> for (i=0;i< MAX_NUM; i++)
> printf("Element %d has value : %d", i,*(data[i])) ;[/color]

data is a pointer to union. data[i] is the i-th union pointed to. The
dereference operator is defined to work only on pointers. data[i] is
not a pointer but an actual union.[color=blue]
>
> for (i=0;i< MAX_NUM; i++)
> free(data[i]) ;
>}
>
>It is obviously wrong (illegal indirection etc). This is schoolboy stuff
>and embarassingly, I've forgotten how to fix it! (using C++ and STL
>libraries for too long!).
>
>Any help or pointers (pun intended) much appreciated[/color]

I think you want data to be a pointer to some number of pointers to
union. Then you want to allocate space for data to point to. Then
you want to allocate space for each pointer in the space to point to.
This last allocation will create space for each of the unions.


<<Remove the del for email>>
Closed Thread


Similar C / C++ bytes