jacob navia said:
static void AddToDataSegment(long long value,int siz)
{
short *pShort;
int *pInt;
long long *pLongLong;
switch (siz) {
case 1:
DataSegment[DataSegmentIndex] = (char)(value&0xff);
break;
case 2:
pShort = (short *)(&DataSegment[DataSegmentIndex]);
*pShort = (short)(value&0xffff);
break;
case 4:
pInt = (int *)(&DataSegment[DataSegmentIndex]);
*pInt = (int)(value&0xffffffff);
break;
case 8:
pLongLong = (long long *)(&DataSegment[DataSegmentIndex]);
*pLongLong = value;
break;
default:
assert(0);
}
}
I would attempt to avoid the above entirely in the first place,
but give the above interface, I would probably write this as:
/*
* Writes a value (supplied here as a long long) to
* DataSegment[DataSegmentIndex .. DataSegmentIndex + siz - 1]
* using the host machine's byte order, whatever that is.
* Makes the nonportable assumption that sizeof(short)==2,
* sizeof(int)==4, and sizeof(long long)==8, when int16_t,
* int32_t, and int64_t are not available.
*
* Note that the supplied value is assumed to fit in the
* target type, in all cases. For instance, supplying siz==1
* means that value should be between CHAR_MIN and CHAR_MAX
* inclusive (typically -128 to 127, or 0 to 255). If the
* value is out of range the effect is undefined.
*/
static void AddToDataSegment(long long value, int siz) {
char *p = &DataSegment[DataSegmentIndex];
#ifdef INT16_MAX
int16_t sval;
#else
short sval;
#endif
#ifdef INT32_MAX
int32_t ival;
#else
int ival;
#endif
#ifdef INT64_MAX
int64_t llval;
#else
long long llval;
#endif
switch (siz) {
case 1:
*p = value;
break;
case 2:
sval = value;
memcpy(p, &sval, siz);
break;
case 4:
ival = value;
memcpy(p, &ival, siz);
break;
case 8:
llval = value;
memcpy(p, &llval, siz);
break;
default:
panic("AddToDataSegment");
/* NOTREACHED */
}
}
This avoids any alignment constraints. The code is designed to
offer a smart compiler easy opportunities for optimization, too:
little-endian machines could turn this into:
[when siz==2, 4, or 8]
copy "value" from argument register(s) to llval-in-memory
push (value of p)
push (address of llval)
push (siz)
call memcpy
where big-endian machines could get:
copy "value" from argument register(s) to llval-in-memory
push (value of p)
push (address of llval + 8 - siz)
push (siz)
call memcpy
and then perhaps expand memcpy in-line if appropriate.