[comp.lang.c] Mixing types in arrays

cc100aa@prism.gatech.EDU (Ray Spalding) (02/15/91)

I keep finding myself wanting to store shorts and longs (as well as
chars) in arrays of char, such as in the following simple example.

This works on all the systems I've tried, but is it "guaranteed"?  I
guess I'm worried that a pointer to char cast into a pointer to long
might somehow point to the wrong place.

I know (a) converting the value to char (e.g., ASCII) would be
guaranteed, but, I want to minimize storage space (and conversion
overhead); (b) the mixed array, if written to a file and read by
another system, would not necessarily be intelligible; and (c) the
example is not optimized (for purposes of clarity and focusing on the
issue at hand rather than other details).

But, are there other pitfalls?  Systems on which this won't work?  A
better way?

char *strcpy();

int
savevalue(key,value,bufptr)
	char *key;
	long value;
	char *bufptr;
{
	*(long *)bufptr = value;
	bufptr += sizeof value;
	(void) strcpy(bufptr,key);
	return sizeof value + strlen(key) + 1;
}

long
getvalue(key,bufptr,bufend)
	char *key;
	char *bufptr;
	char *bufend;
{
	while (bufptr < bufend) {
		if (strcmp(key,bufptr+sizeof(long)) == 0) {
			return *(long*)bufptr;
		}
		bufptr += sizeof(long);
		bufptr += strlen(bufptr) + 1;
	}
	printf("%s not found.\n",key);
	return -1;
}

main()
{
	char buffer[1000];
	char *bufptr = buffer;
	long value;

	bufptr += savevalue("First item",1234567L,bufptr);
	bufptr += savevalue("Second item",987654321L,bufptr);
	bufptr += savevalue("Third item",33333333L,bufptr);
	value = getvalue("Second item",buffer,bufptr);
	if (value == 987654321L) {
		printf("It worked.\n");
	} else {
		printf("It didn't work.\n");
	}
	return 0;
}
-- 
Ray Spalding, Technical Services, Office of Information Technology
Georgia Institute of Technology, Atlanta Georgia, 30332-0715
uucp:     ...!{allegra,amd,hplabs,ut-ngp}!gatech!prism!cc100aa
Internet: cc100aa@prism.gatech.edu

steve@wattres.uucp (Steve Watt) (02/15/91)

In article <22040@hydra.gatech.EDU> cc100aa@prism.gatech.EDU (Ray Spalding) writes:
>I keep finding myself wanting to store shorts and longs (as well as
>chars) in arrays of char, such as in the following simple example.
[ stuff deleted ]
>But, are there other pitfalls?  Systems on which this won't work?  A
>better way?

One system that this won't work on is the IBM RT (at least under AIX), because
a non-aligned integer (read 32 bit) access will get *garbage* in various places.
It will produce 'fixed up unaligned access at xxxxxxxxx for pid xxxx' on the
DECStation, unless the message is turned off, and will probably blow in strange
and subtle ways on other RISC systems.

A better way?  Use a struct?  Probably not as compact, but *much* more obvious.

For example, the code (left to the reader) for the following definitions could
do (mostly) the same thing, but the search (even linear!) is quite a bit
quicker, since it isn't calling strlen all the time.

    typedef struct {
      long value;
      char key[1];
    } item;

    item *data[1000];

Yes, you have to malloc a copy every time, but that's not so bad.  But you
can easily play all of the various data structure optimization games from
here (binary searches with ordered list, etc...)
Have fun!
-- 
Steve Watt
...!claris!wattres!steve		wattres!steve@claris.com also works
Never trust a computer bigger than you can lift.