long type in solaris

C

christian.bau

Hi!
I'm using c language.
I need to copy a long type value into a char string using a memcpy
function:
memcpy(string, (long *) value, len)
this value will be then insert into a database.

On windows machine it works well, on Solaris not. The windows and
solaris path into c language is the same.
I'd like to say also that real value works correctly also if they are
used in the same manner:
memcpy(string, (real *) value, len)

Is there a particular manner to use long values on solaris?
Or to use memcpy with long types?

Could I suggest that you find someone who knows C and is patient, show
them the code, explain what you want to achieve and get their advice?

What you have been posting here makes me very, very afraid what will
happen to your database.
 
C

Chris Torek

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.
 
K

Keith Thompson

jacob navia said:
The code I have is this

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 had another couple of thoughts about this code.

If the siz argument happens to be constant for each call, you could
break this up into 4 separate functions, each of which just uses the
appropriate type. You have to know the siz argument when writing a
call; having to know which function to call is no more difficult. If
the siz argument isn't always constant, you can't do this.

Also, why "siz" rather than "size"?
 
J

jacob navia

Chris Torek a écrit :
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.

Thanks for the suggestions. I am writing this assembler in a hurry,
and you are right, I should have used C99 types, since IBM has a C99
compliant setup. I use IBM compiler to bootstrap mine, so the code has
to compile in both.
 
J

jacob navia

Keith Thompson a écrit :
jacob navia said:
The code I have is this

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 had another couple of thoughts about this code.

If the siz argument happens to be constant for each call, you could
break this up into 4 separate functions, each of which just uses the
appropriate type. You have to know the siz argument when writing a
call; having to know which function to call is no more difficult. If
the siz argument isn't always constant, you can't do this.

It can be ONLY 1, 2 4 or 8. I am sorry about the code but I am
writing it in a hurry. It is the first assembler I wrote since
two years or so, and I am a bit rusty. Anyway, I have planned
a cleanup phase later on, so I will come back to this and see
if I can change that to a function call. But switch is more readable
too...
Also, why "siz" rather than "size"?

I don't really know. It is an identifier that I use since years and
years and all sizes are siz. Why did I start doing this? I do not
remember, just an habit.

jacob
 
K

Keith Thompson

jacob navia said:
Thanks for the suggestions. I am writing this assembler in a hurry,
and you are right, I should have used C99 types, since IBM has a C99
compliant setup. I use IBM compiler to bootstrap mine, so the code has
to compile in both.

IBM has a C99 compliant compiler? Do you mean that it's fully
conforming, or just close enough for your purposes? Which compiler is
it?
 
J

jacob navia

Keith Thompson a écrit :
IBM has a C99 compliant compiler? Do you mean that it's fully
conforming, or just close enough for your purposes? Which compiler is
it?

According to the documentation:
-qlanglvl=<suboptions_list>
Selects the language level and language options for
the compilation. <suboptions_list> is a colon-
separated list of suboptions. The suboptions are:

[snip long list of C89 and other standards supported]

stdc99
Compilation conforms to the ISO C99 standard.
extc89
Compilation conforms to the ANSI C89 standard,
and accepts implementation-specific language
extensions.
extc99
Compilation conforms to the ISO C99 standard,
and accepts implementation-specific language
extensions.

There are no other restrictions in the documentation. It is a very
flexible compiler, can compile 32/64 bits, with vectorization options
and optimizations options, very sophisticated.

[jacob@ppcibm lccppc]$ cc -qversion
IBM XL C/C++ Enterprise Edition V8.0 for AIX
Version: 08.00.0000.0000
[jacob@ppcibm lccppc]$
 
M

matevzb

Keith Thompson a écrit :
[...]
Thanks for the suggestions. I am writing this assembler in a hurry,
and you are right, I should have used C99 types, since IBM has a C99
compliant setup. I use IBM compiler to bootstrap mine, so the code has
to compile in both.
IBM has a C99 compliant compiler? Do you mean that it's fully
conforming, or just close enough for your purposes? Which compiler is
it?According to the documentation:
-qlanglvl=<suboptions_list>
Selects the language level and language options for
the compilation. <suboptions_list> is a colon-
separated list of suboptions. The suboptions are:

[snip long list of C89 and other standards supported]

stdc99
Compilation conforms to the ISO C99 standard.
extc89
Compilation conforms to the ANSI C89 standard,
and accepts implementation-specific language
extensions.
extc99
Compilation conforms to the ISO C99 standard,
and accepts implementation-specific language
extensions.

There are no other restrictions in the documentation. It is a very
flexible compiler, can compile 32/64 bits, with vectorization options
and optimizations options, very sophisticated.
According to the Compiler Reference (found at
http://www-1.ibm.com/support/docvie...ix&uid=swg27006715&loc=en_US&cs=utf-8&lang=en),
the compiler itself is conforming, but the headers/libraries may not
be:
"-qlanglvl <suboptions>
suboption: stdc99
Compilation conforms to the ISO C99 standard. Note: Not all
operating system releases support the header files and runtime library
required by C99."
 
J

jacob navia

matevzb a écrit :
"-qlanglvl <suboptions>
suboption: stdc99
Compilation conforms to the ISO C99 standard. Note: Not all
operating system releases support the header files and runtime library
required by C99."

Old releases of the OS probably are buggy. That covers those old
software. I haven't seen anything suspicious.
 

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,776
Messages
2,569,603
Members
45,196
Latest member
ScottChare

Latest Threads

Top