I'm writing an application which should both compile under 32bit and 64bit
linux on x86 and amd64 hardware.
One function looks like the following:
void f1(int nFlag, void *pOption)
{
if (nFlag == A)
UseOptionAsString((char *) pOption);
if (nFlag == B)
UseOptionAsInt((int) pOption);
}
The idea is that the flag tells you how the option parameter should be
treated. On 32 bit platform this works fine but naturally I'm getting
typecast warnings under AMD64. The problem is that "void *" is 64 bit
whereas int is 32 bit. I already know the values in those cases are smaller
then 64 bit so I don't care about throwing away the upper 32 bit.
Whats the best way to treat such situations?
I could always do a macro like:
#define MY_INT_TYPE (x) (int) (x & 0xFFFFFFFF)
There might be better ways though?
Thanks in advance.
-- John
|
|
0
|
|
|
|
Reply
|
John
|
12/24/2005 9:25:08 PM |
|
"John Smith" <js@x-formation.com> writes:
> I'm writing an application which should both compile under 32bit and
> 64bit linux on x86 and amd64 hardware.
>
> One function looks like the following:
>
> void f1(int nFlag, void *pOption)
> {
> if (nFlag == A)
> UseOptionAsString((char *) pOption);
> if (nFlag == B)
> UseOptionAsInt((int) pOption);
> }
>
> The idea is that the flag tells you how the option parameter should
> be treated. On 32 bit platform this works fine but naturally I'm
> getting typecast warnings under AMD64. The problem is that "void *"
> is 64 bit whereas int is 32 bit. I already know the values in those
> cases are smaller then 64 bit so I don't care about throwing away
> the upper 32 bit. Whats the best way to treat such situations? I
> could always do a macro like: #define MY_INT_TYPE (x) (int) (x &
> 0xFFFFFFFF)
>
> There might be better ways though?
One possibility that would let the compiler figure it out:
typedef struct {
union {
char * pOption;
int iOption;
};
int optionType;
} Option;
Joe
--
Gort, klatu barada nikto
|
|
0
|
|
|
|
Reply
|
joe
|
12/24/2005 9:42:35 PM
|
|
On Sat, 24 Dec 2005, John Smith wrote:
> void f1(int nFlag, void *pOption)
> {
> if (nFlag == A)
> UseOptionAsString((char *) pOption);
> if (nFlag == B)
> UseOptionAsInt((int) pOption);
> }
Yuck--Hungarian notation. Best leave that to the Windoze programmers...
> The idea is that the flag tells you how the option parameter should be
> treated. On 32 bit platform this works fine but naturally I'm getting
> typecast warnings under AMD64. The problem is that "void *" is 64 bit
> whereas int is 32 bit. I already know the values in those cases are smaller
> then 64 bit so I don't care about throwing away the upper 32 bit.
> Whats the best way to treat such situations?
Assuming there's no way to avoid this kludge in the first place,
how about casting to long rather than int? In the LP64 programming
model, both longs and pointers are 64-bit quantities.
HTH,
--
Rich Teer, SCNA, SCSA, OpenSolaris CAB member
. * * . * .* .
. * . .*
President, * . . /\ ( . . *
Rite Online Inc. . . / .\ . * .
.*. / * \ . .
. /* o \ .
Voice: +1 (250) 979-1638 * '''||''' .
URL: http://www.rite-group.com/rich ******************
|
|
0
|
|
|
|
Reply
|
Rich
|
12/25/2005 1:23:35 AM
|
|
Rich Teer wrote:
> Yuck--Hungarian notation. Best leave that to the Windoze programmers...
Holy truth. But not programmers, rather developer$.
> > The idea is that the flag tells you how the option parameter should be
> > treated. On 32 bit platform this works fine but naturally I'm getting
> > typecast warnings under AMD64. The problem is that "void *" is 64 bit
> > whereas int is 32 bit. I already know the values in those cases are smaller
> > then 64 bit so I don't care about throwing away the upper 32 bit.
> > Whats the best way to treat such situations?
>
> Assuming there's no way to avoid this kludge in the first place,
> how about casting to long rather than int? In the LP64 programming
> model, both longs and pointers are 64-bit quantities.
And linux kernel is build upon assumption that unsigned long can
represent a virtual address on any currently supported system, while
64-bit systems being among of them.
|
|
0
|
|
|
|
Reply
|
Maxim
|
12/26/2005 12:42:13 AM
|
|
"John Smith" <js@x-formation.com> writes:
>The idea is that the flag tells you how the option parameter should be
>treated. On 32 bit platform this works fine but naturally I'm getting
>typecast warnings under AMD64. The problem is that "void *" is 64 bit
>whereas int is 32 bit. I already know the values in those cases are smaller
>then 64 bit so I don't care about throwing away the upper 32 bit.
>Whats the best way to treat such situations?
>I could always do a macro like:
>#define MY_INT_TYPE (x) (int) (x & 0xFFFFFFFF)
>There might be better ways though?
Use "intptr_t" as integer type.
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
|
|
0
|
|
|
|
Reply
|
Casper
|
12/26/2005 10:05:47 AM
|
|
Casper H.S. Dik wrote:
[]
> >There might be better ways though?
>
> Use "intptr_t" as integer type.
Unfortunately, support for intptr_t is optional, and for example, it
was not available on an up-to-date SLES system this summer, while FC4
did support it.
|
|
0
|
|
|
|
Reply
|
Maxim
|
12/26/2005 1:14:06 PM
|
|
Sat, Dec 24, 2005 at 22:25:08, js (John Smith) wrote about "Casting between 64bit and 32bit":
JS> void f1(int nFlag, void *pOption)
JS> {
JS> if (nFlag == A)
JS> UseOptionAsString((char *) pOption);
JS> if (nFlag == B)
JS> UseOptionAsInt((int) pOption);
JS> }
JS> The idea is that the flag tells you how the option parameter should be
JS> treated. On 32 bit platform this works fine but naturally I'm getting
JS> typecast warnings under AMD64. The problem is that "void *" is 64 bit
JS> whereas int is 32 bit. I already know the values in those cases are smaller
JS> then 64 bit so I don't care about throwing away the upper 32 bit.
The problem isn't typecast warning (you'll have it here anyway)
but correctness of conversion int -> void* and backwards void* ->
int. I suppose it's correct (in these two stages) even on amd64;
my tests confirm it. OTOH, warning shows the conversion losts
significant bits; but the same happens on i386 with substition of
int with short, and you can't avoid these warnings. If they really
annoy, use not integer value passed as pointer, but pointer to
passed integer value.
Another way to avoid warning is to convert in following manner:
UseOptionAsInt((int)(long)pOption);
-netch-
|
|
0
|
|
|
|
Reply
|
Valentin
|
12/27/2005 6:03:09 PM
|
|
Thanks for all the answers.
As some people pointed out I solved it in most cases by casting to either
"unsigned long long" or "unsigned long" and then followed by an integer
cast.
One typical example of the sitations I've fixed:
void socket_handler_thread(void *param)
{
int socket = (int) (unsigned long) param;
....
}
To my surprise it turned out unsigned long is 64 bit under linux x86_64
where I assumed it was 32 bit as Windows. I guess 64 bit Windows and Linux
does not use the same 64 bit model. This caused lots of problem which needed
to be fixed.
Looking into sys/types.h it seems 32 bit DWORD's are defined as unsigned
int.
Thanks.
-- John
|
|
0
|
|
|
|
Reply
|
John
|
12/28/2005 9:36:40 AM
|
|
John Smith wrote:
> To my surprise it turned out unsigned long is 64 bit under linux x86_64
> where I assumed it was 32 bit as Windows. I guess 64 bit Windows and Linux
> does not use the same 64 bit model. This caused lots of problem which needed
Your guess is correct. See:
http://www-128.ibm.com/developerworks/library/l-pow-inteltopwr/
http://msdn.microsoft.com/library/en-us/win64/win64/abstract_data_models.asp
http://www.unix.org/version2/whatsnew/lp64_wp.html
--
mail1dotstofanetdotdk
|
|
0
|
|
|
|
Reply
|
Bjorn
|
12/28/2005 1:24:13 PM
|
|
Wed, Dec 28, 2005 at 10:36:40, js (John Smith) wrote about "Casting between 64bit and 32bit":
JS> To my surprise it turned out unsigned long is 64 bit under linux x86_64
JS> where I assumed it was 32 bit as Windows. I guess 64 bit Windows and Linux
JS> does not use the same 64 bit model. This caused lots of problem which needed
JS> to be fixed.
Yes, difference between Unix (most flavors) and MS Windows on x86-64
(a.k.a. amd64) in type sizes is that Windows has 32-bit long, but
Unix has 64-bit long.
To justify each of this decision one can say Windows tried to keep
maximal compatibility with existing applications, OTOH Unixes has
long tradition to use 64-bit systems and types were aligned to
values the same as for other 64-bit systems (Alpha, Power, Sparc64).
This isn't the only difference; most ABI details differ.
If you want to use fixed-width types for all platforms, use
[u]int32_t and [u]int64_t required by C99.
-netch-
|
|
0
|
|
|
|
Reply
|
Valentin
|
12/29/2005 9:46:25 AM
|
|
> If you want to use fixed-width types for all platforms, use
> [u]int32_t and [u]int64_t required by C99.
>
Yes so I found out in sys/types.h. It's just too bad that not compilers
support the C99 extensions. Atleast these macros you mention are something I
would not trust for now.
Just checking it seems my Fedora Core 3 installation doesn't have uint32_t
but u_int32_t instead.
Unfortunatly it doesn't seem that easy to change yet.
-- John
|
|
0
|
|
|
|
Reply
|
John
|
12/29/2005 10:24:44 AM
|
|
Thu, Dec 29, 2005 at 11:24:44, js (John Smith) wrote about "Casting between 64bit and 32bit":
>> If you want to use fixed-width types for all platforms, use
>> [u]int32_t and [u]int64_t required by C99.
JS> Yes so I found out in sys/types.h. It's just too bad that not compilers
JS> support the C99 extensions. Atleast these macros you mention are something I
JS> would not trust for now.
JS> Just checking it seems my Fedora Core 3 installation doesn't have uint32_t
JS> but u_int32_t instead.
Hm. C99 requires they shall be defined in <stdint.h>. I haven't
Fedora Core 3, but Fedora Core 4 is available and knows these types
in <stdint.h>
Types named u_intN_t are BSD old-styled types.
-netch-
|
|
0
|
|
|
|
Reply
|
Valentin
|
12/29/2005 10:52:36 AM
|
|
John Smith wrote:
>> If you want to use fixed-width types for all platforms, use
>> [u]int32_t and [u]int64_t required by C99.
>>
>
> Yes so I found out in sys/types.h. It's just too bad that not compilers
> support the C99 extensions. Atleast these macros you mention are something I
> would not trust for now.
>
> Just checking it seems my Fedora Core 3 installation doesn't have uint32_t
> but u_int32_t instead.
It has uint32_t, you get it by including stdint.h
(note that it might not be defined in stdint.h directly)
If you want, you could make your own stdint.h for systems lacking it.
Just make sure it is correct for the platform it's supposed to be used
on :-)
|
|
0
|
|
|
|
Reply
|
ISO
|
12/29/2005 10:59:08 AM
|
|
Valentin Nechayev <netch@segfault.kiev.ua> writes:
>To justify each of this decision one can say Windows tried to keep
>maximal compatibility with existing applications, OTOH Unixes has
>long tradition to use 64-bit systems and types were aligned to
>values the same as for other 64-bit systems (Alpha, Power, Sparc64).
>This isn't the only difference; most ABI details differ.
Long before Solaris 7 (Sun's first release of 64-bit Solaris) saw
the light of day, there was a first ABI (and, I think, Solaris/64 from
HAL which implemented it) for 64 it SPARC CPUs which also used 32 bit
longs in 64 bit mode. Again for maximum compatibility.
But others used 64 bit longs and found that the compatibility issues
simply weren't such a big deal; worse even, the main issue was not
expecting longs to be 32 bit but rather that pointers and ints were
of equal size; but that, again, was mostly not much of an issue
and having a standard integer type for the full size was seen as much
better.
>If you want to use fixed-width types for all platforms, use
>[u]int32_t and [u]int64_t required by C99.
Indeed. (But that still means there's really no reason for Microsoft
to not eat some of the incompatibility cost and go for the larger integers)
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
|
|
0
|
|
|
|
Reply
|
Casper
|
12/29/2005 11:45:00 AM
|
|
"John Smith" <js@x-formation.com> writes:
>> If you want to use fixed-width types for all platforms, use
>> [u]int32_t and [u]int64_t required by C99.
>>
>Yes so I found out in sys/types.h. It's just too bad that not compilers
>support the C99 extensions. Atleast these macros you mention are something I
>would not trust for now.
>Just checking it seems my Fedora Core 3 installation doesn't have uint32_t
>but u_int32_t instead.
>Unfortunatly it doesn't seem that easy to change yet.
That's weird because the types have been specified for eons now.
They're not in inttypes.h either?
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
|
|
0
|
|
|
|
Reply
|
Casper
|
12/29/2005 11:45:44 AM
|
|
Valentin Nechayev wrote:
> If you want to use fixed-width types for all platforms, use
> [u]int32_t and [u]int64_t required by C99.
Actually, C99 paragraph 7.18.1.1/3 says:
"These types are optional. However, if an implementation provides
integer types with widths of 8, 16, 32, or 64 bits, it shall define
the corresponding typedef names."
However, SUSv3 [1] is a bit more explicit as it requires [u]int8_t,
[u]int16_t, and [u]int32_t. The [u]int64_t type is only required if
available.
If the solution can be restricted to C99, then there are other options:
o Minimum-width integer types (required by C99): [u]int_least32_t and
[u]int_least64_t
o Greatest-width integer types (required by C99): [u]intmax_t
o Integer types capable of holding object pointers (optional in C99,
required by X/OPEN): [u]intptr_t
An entirely different solution that the original poster may want to
consider is to use variadic arguments. The disadvantages is that you
loose type-safety.
void f1(int flag, ...)
{
va_list arguments;
va_start(arguments, flag);
switch (flag) {
case A: UseOptionAsString(va_arg(arguments, char *)); break;
case B: UseOptionAsInt(va_arg(arguments, int)); break;
default: assert(0); break;
va_end(arguments);
}
[1] http://www.opengroup.org/onlinepubs/009695399/basedefs/stdint.h.html
--
mail1dotstofanetdotdk
|
|
0
|
|
|
|
Reply
|
Bjorn
|
12/29/2005 12:05:02 PM
|
|
Thu, Dec 29, 2005 at 13:05:02, breese (Bjorn Reese) wrote about "Casting between 64bit and 32bit":
>> If you want to use fixed-width types for all platforms, use
>> [u]int32_t and [u]int64_t required by C99.
BR> Actually, C99 paragraph 7.18.1.1/3 says:
BR> "These types are optional. However, if an implementation provides
BR> integer types with widths of 8, 16, 32, or 64 bits, it shall define
BR> the corresponding typedef names."
Yes, but if you find a platform which doesn't conform to degree-of-2
size hierarchy (2, 4, 8, 16, 32, 64... everywhere and always) this
will give much more inportability than by simple lack of these
types.:))
(I don't say for exceptions as 10-byte native float format for i8087,
they anyway shall be taken into account, but don't refute the common
rule.)
BR> An entirely different solution that the original poster may want to
BR> consider is to use variadic arguments. The disadvantages is that you
BR> loose type-safety.
Really, type safeness isn't case in original approach (e.g. consider
f1(B, "abc"));
-netch-
|
|
0
|
|
|
|
Reply
|
Valentin
|
12/29/2005 4:15:54 PM
|
|
|
16 Replies
369 Views
(page loaded in 0.17 seconds)
|