union | | |
Does anyone see a problem with..
#include <stdio.h>
typedef struct {
float x;
float y;
float z;
} _XYZ_;
typedef union {
float arr[3];
_XYZ_ xyz;
} XYZ;
int main(int argc, char** argv)
{
XYZ vec;
printf("union test\n");
printf("setting array to get _XYZ_\n");
vec.arr[0] = 1.0F;
vec.arr[1] = 2.0F;
vec.arr[2] = 3.0F;
printf("vec.xyz is %f, %f, %f\n", vec.xyz.x,vec.xyz.y,vec.xyz.z);
printf("setting _XYZ_ to get arr\n");
vec.xyz.x = 4.0F;
vec.xyz.y = 5.0F;
vec.xyz.z = 6.0F;
printf("vec.arr[] is %f, %f, %f\n",
vec.arr[0],vec.arr[1],vec.arr[2]);
return 0;
}
... On a side note ..
#include <stdio.h>
int main(int argc, char** argv)
{
printf("%15s %s\n", "TYPE", "SIZE");
printf("%15s %s\n", "---------------", "----");
printf("%15s: %02d %02d\n", "char", sizeof(char),sizeof(char)*8);
printf("%15s: %02d %02d\n", "short", sizeof(short),sizeof(short)*8);
printf("%15s: %02d %02d\n", "int", sizeof(int),sizeof(int)*8);
printf("%15s: %02d %02d\n", "long", sizeof(long),sizeof(long)*8);
printf("%15s: %02d %02d\n", "float", sizeof(float),sizeof(float)*8);
printf("%15s: %02d %02d\n", "double",
sizeof(double),sizeof(double)*8);
printf("%15s: %02d %02d\n", "long int", sizeof(long int),sizeof(long
int)*8);
printf("%15s: %02d %02d\n", "long double", sizeof(long
double),sizeof(long double)*8);
return 0;
}
... produces ..
char: 01 08
short: 02 16
int: 02 16
long: 04 32
float: 04 32
double: 08 64
long int: 04 32
long double: 10 80
(This was compiled and executed on WinXP)
I thought that "int" type was 32-bit native;
and, "long int" was 64-bit native. In every
variety of UNIX that I try this on my thought
is correct. But, when going to a windoze
environment I get these results. Is there a
way to detect the native type sizes that are
available?
Anyway, if I do a union on UNIX such as..
typedef union {
int val;
char bytes[4];
}
... it will be invalid on WinXP.. sheesh!!! | | | | re: union
On Tue, 8 Jun 2004, Bun Head wrote:[color=blue]
>
> Does anyone see a problem with..[/color]
[reformatted to save space in quotation]
[color=blue]
> #include <stdio.h>
> typedef struct {
> float x,y,z;
> } _XYZ_;[/color]
Invasion of implementation namespace with "_X..." This is
unlikely to be a cause of silent errors, though it *is* technically
a case of undefined behavior AFAIK.
[color=blue]
> typedef union {
> float arr[3];
> _XYZ_ xyz;
> } XYZ;
>
> int main(int argc, char** argv)
> {
> XYZ vec;[/color]
[color=blue]
> vec.arr[0] = 1.0F;
> vec.arr[1] = 2.0F;
> vec.arr[2] = 3.0F;
> printf("vec.xyz is %f, %f, %f\n", vec.xyz.x,vec.xyz.y,vec.xyz.z);[/color]
Undefined behavior, because you are trying to read out of the
object 'vec.xyz.y', which has never been initialized. ('vec.xyz.x'
shares the memory location of 'vec.arr[0]', but the same is not
necessarily true of 'y' and '1', or 'z' and '2'.)
In fact, I'm not even sure if the wording of the Standard permits
you to write to 'vec.arr' and then read from 'vec.xyz' without an
intermediate write to 'vec.xyz' in *any* case... but it certainly
happens often enough that it *ought* to be allowed. [As in, I think
I would have heard by now if it weren't.]
[color=blue]
> vec.xyz.x = 4.0F;
> vec.xyz.y = 5.0F;
> vec.xyz.z = 6.0F;
> printf("vec.arr[] is %f, %f, %f\n",
> vec.arr[0],vec.arr[1],vec.arr[2]);[/color]
Same problem here; the value of 'vec.arr[1]' is indeterminate.
[color=blue]
> .. On a side note ..
>
> #include <stdio.h>
>
> int main(int argc, char** argv)
> {
> printf("%15s %s\n", "TYPE", "SIZE");
> printf("%15s %s\n", "---------------", "----");
> printf("%15s: %02d %02d\n", "char", sizeof(char),sizeof(char)*8);[/color]
'%d' format specifier, size_t argument. This is a recipe for
undefined behavior, and your compiler will warn you about it if
you turn the warning level high enough (-W -Wall on gcc, e.g).
The appropriate fix is
printf("%15s: %02lu %02lu\n", "char",
(unsigned long) sizeof (char),
(unsigned long) (8 * sizeof (char)));
And it might interest you to learn that macros can be used in C
to ease the pain of programs like this one:
#define PRINTSIZE(t) printf("%15s: %02lu $02lu\n", #t, \
(unsigned long) sizeof (t), \
(unsigned long) (8 * sizeof (t)))
PRINTSIZE(char);
PRINTSIZE(short);
PRINTSIZE(int);
[...]
PRINTSIZE(long double);
#undef PRINTSIZE
[color=blue]
> char: 01 08
> short: 02 16
> int: 02 16
> long: 04 32
> float: 04 32
> double: 08 64
> long int: 04 32
> long double: 10 80
>
> (This was compiled and executed on WinXP)
>
> I thought that "int" type was 32-bit native;
> and, "long int" was 64-bit native. In every
> variety of UNIX that I try this on my thought
> is correct.[/color]
Then you are lucky. On all the systems to which I have access,
int is long is 32 bits. You should thank your lucky stars to have
access not only to a 64-bit-'long' system, but also a 16-bit-'int'
system. That's uncommon, AFAIK.
In C, the only guarantees you have are that
sizeof(char) == 1
sizeof(char <= sizeof(short) <= sizeof(int) <= sizeof(long)
and that the width of 'char' >= 8 bits,
the widths of 'int' and 'short' >= 16 bits,
and the width of 'long' >= 32 bits.
[color=blue]
> Is there a way to detect the native type sizes that are
> available?[/color]
Sure. You just did.
if (sizeof(int) == 4) {
puts("Hey, 'int' is a 4-byte type!");
}
else if (sizeof(long) == 4) {
puts("Hey, 'long' is a 4-byte type!");
}
et cetera. In C99, I think there are macros that can tell you
whether the implementation defines types int32_t, int64_t, etc.,
or something similar. In general, though, you don't need to
know how big 'int' is, so why bother?
[color=blue]
> Anyway, if I do a union on UNIX such as..
>
> typedef union {
> int val;
> char bytes[4];
> }
>
> .. it will be invalid on WinXP.. sheesh!!![/color]
Not on any major WinXP compiler of which I'm aware.
You're not still trying to run Turbo C on WinXP, are you?
-Arthur | | | | re: union
"Bun Head" <daehnub@yahoo.com> wrote[color=blue]
> Does anyone see a problem with..
>
> #include <stdio.h>
>
> typedef struct {
> float x;
> float y;
> float z;
> } _XYZ_;
>
> typedef union {
> float arr[3];
> _XYZ_ xyz;
> } XYZ;
>
> int main(int argc, char** argv)
> {
> XYZ vec;
>
> printf("union test\n");
>
> printf("setting array to get _XYZ_\n");
> vec.arr[0] = 1.0F;
> vec.arr[1] = 2.0F;
> vec.arr[2] = 3.0F;
> printf("vec.xyz is %f, %f, %f\n", vec.xyz.x,vec.xyz.y,vec.xyz.z);
>[/color]
This is illegal. You have set the union using the "arr" member, then you try
to access it using the "x", "y" and "z" members.
On most platforms this will work OK but there is no guarantee. | | | | re: union
On 8 Jun 2004 13:51:34 -0700, in comp.lang.c , daehnub@yahoo.com (Bun Head)
wrote:
[color=blue]
>Does anyone see a problem with..
>
>#include <stdio.h>
>
>typedef struct {
> float x;
> float y;
> float z;
>} _XYZ_;[/color]
This name possibly invades compiler namespace. Dont use leading underscores
in type or variable names.
[color=blue]
>typedef union {
> float arr[3];
> _XYZ_ xyz;
>} XYZ;[/color]
while it might seem that arr and xyz are coincident in memory, they may not
be - xyz may contain packing between the structure members.
(snip example setting a union via one member and reading it via another)
writing to one union member and reading from another is unspecified
behaviour ie its not guaranteed to be meaningful. That said, its a common
extension to put meaning to this behaviour.
[color=blue]
>I thought that "int" type was 32-bit native;
>and, "long int" was 64-bit native. In every[/color]
The size of both is implementation-specific and need not relate to any
hardware optimum.
[color=blue]
>variety of UNIX that I try this on my thought
>is correct. But, when going to a windoze
>environment I get these results. Is there a
>way to detect the native type sizes that are
>available?[/color]
You just did.
[color=blue]
>Anyway, if I do a union on UNIX such as..
>
>typedef union {
> int val;
> char bytes[4];
>}
>
>.. it will be invalid on WinXP.. sheesh!!![/color]
Its valid, you're just making nonportable assumptions. Don't do that.
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==---- http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==---- http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =--- | | | | re: union
Malcolm wrote:
[color=blue]
> This is illegal. You have set the union using the "arr" member, then you try
> to access it using the "x", "y" and "z" members.
> On most platforms this will work OK but there is no guarantee.[/color]
It's implementation-defined, not illegal. The implementation could of
course define that as a runtime fault or something else dire.
Brian Rodenborn | | | | re: union
Bun Head wrote:
[color=blue]
> Does anyone see a problem with..
>
> #include <stdio.h>
>
> typedef struct XYZ_t {
> float x;
> float y;
> float z;
> } XYZ_t;
>
> typedef union XYZ {
> float arr[3];
> XYZ_t xyz;
> } XYZ;
>
> int main(int argc, char* argv[]) {
>
> XYZ vec;
>
> printf("union test\n");
>
> printf("setting array to get XYZ_t\n");
> vec.arr[0] = 1.0F;
> vec.arr[1] = 2.0F;
> vec.arr[2] = 3.0F;
> printf("vec.xyz is %f, %f, %f\n",
> vec.xyz.x, vec.xyz.y, vec.xyz.z);
> printf("setting XYZ_t to get arr\n");
> vec.xyz.x = 4.0F;
> vec.xyz.y = 5.0F;
> vec.xyz.z = 6.0F;
> printf("vec.arr[] is %f, %f, %f\n",
> vec.arr[0], vec.arr[1], vec.arr[2]);
>
> return 0;
> }[/color]
Not really. It will port anywhere.
[color=blue]
>
> .. On a side note ..
>
> #include <stdio.h>
>
> int main(int argc, char** argv) {
>
> printf("%15s %s\n", "TYPE", "SIZE");
> printf("%15s %s\n", "---------------", "----");
> printf("%15s: %02d %02d\n", "char", sizeof(char), sizeof(char)*8);
> printf("%15s: %02d %02d\n", "short", sizeof(short), sizeof(short)*8);
> printf("%15s: %02d %02d\n", "int", sizeof(int), sizeof(int)*8);
> printf("%15s: %02d %02d\n", "long", sizeof(long), sizeof(long)*8);
> printf("%15s: %02d %02d\n", "float", sizeof(float), sizeof(float)*8);
> printf("%15s: %02d %02d\n",
> "double", sizeof(double), sizeof(double)*8);
> printf("%15s: %02d %02d\n",
> "long int", sizeof(long int), sizeof(long int)*8);
> printf("%15s: %02d %02d\n",
> "long double", sizeof(long double), sizeof(long double)*8);
>
> return 0;
> }
>
> .. produces ..
>
> char: 01 08
> short: 02 16
> int: 02 16
> long: 04 32
> float: 04 32
> double: 08 64
> long int: 04 32
> long double: 10 80
>
> (This was compiled and executed on WinXP)
>
> I thought that "int" type was 32-bit native;
> and, "long int" was 64-bit native.
> In every variety of UNIX that I try this on,
> my thought is correct.
> But, when going to a windoze environment,
> I get these results.
> Is there a way to detect the native type sizes
> that are available?[/color]
#include <stdint.h>
[color=blue]
> Anyway, if I do a union on UNIX such as...
>
> typedef union Some_t {
> int val;
> char bytes[4];
> } Some_t;
>
> .. it will be invalid on WinXP.. sheesh![/color]
Try:
#include <stdint.h>
typedef union Some_t {
int32_t val;
char bytes[4];
} Some_t; | | | | re: union
Bun Head wrote:[color=blue]
> .. On a side note ..
>
> #include <stdio.h>
>
> int main(int argc, char** argv)
> {
> printf("%15s %s\n", "TYPE", "SIZE");
> printf("%15s %s\n", "---------------", "----");
> printf("%15s: %02d %02d\n", "char", sizeof(char),sizeof(char)*8);
> printf("%15s: %02d %02d\n", "short", sizeof(short),sizeof(short)*8);
> printf("%15s: %02d %02d\n", "int", sizeof(int),sizeof(int)*8);
> printf("%15s: %02d %02d\n", "long", sizeof(long),sizeof(long)*8);
> printf("%15s: %02d %02d\n", "float", sizeof(float),sizeof(float)*8);
> printf("%15s: %02d %02d\n", "double",
> sizeof(double),sizeof(double)*8);
> printf("%15s: %02d %02d\n", "long int", sizeof(long int),sizeof(long
> int)*8);
> printf("%15s: %02d %02d\n", "long double", sizeof(long
> double),sizeof(long double)*8);
>
> return 0;
> }
>
> .. produces ..
>
> char: 01 08
> short: 02 16
> int: 02 16
> long: 04 32
> float: 04 32
> double: 08 64
> long int: 04 32
> long double: 10 80
>
> (This was compiled and executed on WinXP)
>
> I thought that "int" type was 32-bit native;
> and, "long int" was 64-bit native. In every[/color]
On Win32, "int" bits and "long int" are usually both 32 bits. Try a
different compiler or different compiler flags.
Also note that a char is not guaranteed to be exactly 8 bits wide.
(although it almost certainly will be on any x86 machine)
With MSVC Toolkit 2003 on Windows 2000, I get:
TYPE SIZE
--------------- ----
char: 01 08
short: 02 16
int: 04 32
long: 04 32
float: 04 32
double: 08 64
long int: 04 32
long double: 08 64
-josh | | | | re: union daehnub@yahoo.com (Bun Head) wrote in message news:<f47fc66e.0406081251.f34f4ef@posting.google.c om>...[color=blue]
>
> Anyway, if I do a union on UNIX such as..
>
> typedef union {
> int val;
> char bytes[4];
> }
>
> .. it will be invalid on WinXP.. sheesh!!![/color]
It's unlikely to be invalid on WinXP, but why the "sheesh"?
Where did that magic number '4' come from? Why did you go
to the trouble of finding it out or dreaming it up? If you
want the char array to be the same size as an int, then
the obvious thing to code is
typedef union {
int val;
char bytes[sizeof(int)];
} u; | | | | re: union
E. Robert Tisdale wrote:[color=blue]
> Bun Head wrote:
>[color=green]
>> Does anyone see a problem with..[/color][/color]
(code snipped)[color=blue]
>
> Not really. It will port anywhere.[/color]
Not to the DS9000 it won't.
[color=blue]
>[color=green]
>> Anyway, if I do a union on UNIX such as...
>>
>> typedef union Some_t {
>> int val;
>> char bytes[4];
>> } Some_t;
>>
>> .. it will be invalid on WinXP.. sheesh![/color]
>
> Try:
>
> #include <stdint.h>
> typedef union Some_t {
> int32_t val;
> char bytes[4];
> } Some_t;[/color]
Might work on WinXP, but what about platforms where sizeof (int32_t) == 1? | | | | re: union
Emlyn Peter Corrin wrote:
[color=blue]
> Might work on WinXP, but what about platforms where sizeof (int32_t) == 1?[/color]
Which platforms are those? | | | | re: union
"E. Robert Tisdale" <E.Robert.Tisdale@jpl.nasa.gov> wrote in message
news:ca70u2$6op$1@nntp1.jpl.nasa.gov...[color=blue]
> Emlyn Peter Corrin wrote:
>[color=green]
> > Might work on WinXP, but what about platforms where sizeof > > (int32_t)[/color][/color]
== 1?[color=blue]
>
> Which platforms are those?
>[/color]
Some super-computers can only read memory in 32-bit bytes, which creates
problems for people writing C compilers. One solution is to mess around with
pointer internals to create the illusion of 8 bit bytes, the other is to
have 32-bit chars. | | | | re: union
Malcolm wrote:[color=blue]
> "E. Robert Tisdale" <E.Robert.Tisdale@jpl.nasa.gov> wrote in message
> news:ca70u2$6op$1@nntp1.jpl.nasa.gov...[color=green]
>> Emlyn Peter Corrin wrote:
>>[color=darkred]
>>> Might work on WinXP, but what about platforms where
>>> sizeof (int32_t) == 1?[/color]
>>
>> Which platforms are those?
>>[/color]
> Some super-computers can only read memory in 32-bit bytes, which
> creates problems for people writing C compilers. One solution is to
> mess around with pointer internals to create the illusion of 8 bit
> bytes, the other is to have 32-bit chars.[/color]
As well as some embedded processors.
The point is, why not use portable code when it's just as easy to write as
the non-portable version, especially when it better expresses the intent.
i.e.
typedef union Some_t {
some_type val;
char bytes[sizeof (some_type)];
} Some_t; | | | | re: union
In <ca85hb$1sk$1@news6.svr.pol.co.uk> "Malcolm" <malcolm@55bank.freeserve.co.uk> writes:
[color=blue]
>"E. Robert Tisdale" <E.Robert.Tisdale@jpl.nasa.gov> wrote in message
>news:ca70u2$6op$1@nntp1.jpl.nasa.gov...[color=green]
>> Emlyn Peter Corrin wrote:
>>[color=darkred]
>> > Might work on WinXP, but what about platforms where sizeof > > (int32_t)[/color][/color]
>== 1?[color=green]
>>
>> Which platforms are those?
>>[/color]
>Some super-computers can only read memory in 32-bit bytes,[/color]
Concrete examples, please.
[color=blue]
>which creates
>problems for people writing C compilers. One solution is to mess around with
>pointer internals to create the illusion of 8 bit bytes, the other is to
>have 32-bit chars.[/color]
Concrete examples of implementations with 32-bit chars for super-computers
please.
The only thing remotely resembling this description was the original
Alpha processor, whose memory system was 8-bit based, but that couldn't
read entities smaller than 32 bits. Yet, all the implementations for
the 21064 chip used 8-bit bytes and tried to optimise character
processing as much as possible.
The 32-bit bytes must be searched at the opposite end of the spectrum:
DSP chips for embedded control applications and their freestanding
implementations. Such things are not used for character processing, so
making char a 32-bit type doesn't waste any resources.
Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan.Pop@ifh.de | | | | re: union
Emlyn Corrin wrote:[color=blue]
>[/color]
.... snip ...[color=blue]
>
> The point is, why not use portable code when it's just as easy
> to write as the non-portable version, especially when it better
> expresses the intent.
>
> i.e.
> typedef union Some_t {
> some_type val;
> char bytes[sizeof (some_type)];
> } Some_t;[/color]
Because it isn't portable code if used as a mechanism to access
the representation of some_type. Worse, the usual implementations
will appear to work.
--
Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address! | | | | re: union
On Tue, 8 Jun 2004 17:22:26 -0400 (EDT), "Arthur J. O'Dwyer"
<ajo@nospam.andrew.cmu.edu> wrote:
[color=blue]
>
> On Tue, 8 Jun 2004, Bun Head wrote:[/color]
[color=blue][color=green]
> > I thought that "int" type was 32-bit native;
> > and, "long int" was 64-bit native. In every
> > variety of UNIX that I try this on my thought
> > is correct.[/color]
>[/color]
Every(? at least most) Unix variety *now common*, probably, but
certainly there have been Unices and Unix-alikes, including the
original, that were not I32L64.
[color=blue]
> Then you are lucky. On all the systems to which I have access,
> int is long is 32 bits. You should thank your lucky stars to have
> access not only to a 64-bit-'long' system, but also a 16-bit-'int'
> system. That's uncommon, AFAIK.
> In C, the only guarantees you have are that
>
> sizeof(char) == 1
> sizeof(char <= sizeof(short) <= sizeof(int) <= sizeof(long)
>[/color]
Nit: you aren't actually *guaranteed* the sizes are nondecreasing;
only that sizeof (all flavors of) char is 1 and sizeof any other type
is >= 1 (and integral). You are guaranteed that the _widths_, i.e.
number of significant bits, are nondecreasing, and in practice this
means the sizes also are.
[color=blue]
> and that the width of 'char' >= 8 bits,
> the widths of 'int' and 'short' >= 16 bits,
> and the width of 'long' >= 32 bits.
>[/color]
Right. And 'long long' >= 64 bits in C99; and nondecreasing from char
to short to int to long (to long long). And the same for unsigneds.
[color=blue][color=green]
> > Is there a way to detect the native type sizes that are
> > available?[/color]
>
> Sure. You just did.
>
> if (sizeof(int) == 4) {
> puts("Hey, 'int' is a 4-byte type!");
> }
> else if (sizeof(long) == 4) {
> puts("Hey, 'long' is a 4-byte type!");
> }
>[/color]
You can also check the value ranges, which are clumsier but may
actually be better at determining whether a type is suitable for some
purpose, at compile time with <limits.h> and preprocessor arithmetic.
[color=blue]
> et cetera. In C99, I think there are macros that can tell you
> whether the implementation defines types int32_t, int64_t, etc.,
> or something similar. In general, though, you don't need to
> know how big 'int' is, so why bother?
>[/color]
- David.Thompson1 at worldnet.att.net | | | | re: union
On 8 Jun 2004 13:51:34 -0700, daehnub@yahoo.com (Bun Head) wrote:
[color=blue]
>I thought that "int" type was 32-bit native;
>and, "long int" was 64-bit native. In every
>variety of UNIX that I try this on my thought
>is correct.[/color]
Apparently you haven't tried very many.
--
Al Balmer
Balmer Consulting removebalmerconsultingthis@att.net | | | | re: union
In <igf3d0le4o0tk1amroomv6mf83pkgsft4e@4ax.com> Alan Balmer <albalmer@att.net> writes:
[color=blue]
>On 8 Jun 2004 13:51:34 -0700, daehnub@yahoo.com (Bun Head) wrote:
>[color=green]
>>I thought that "int" type was 32-bit native;
>>and, "long int" was 64-bit native. In every
>>variety of UNIX that I try this on my thought
>>is correct.[/color]
>
>Apparently you haven't tried very many.[/color]
All the Unices with native 64-bit support (which is not the same as all
the Unices running on 64-bit hardware) I'm familiar with behave as
described by Bun Head. For a Unix with no native 64-bit support, there
is no such thing as "64-bit native long int" in the first place.
Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan.Pop@ifh.de |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,533 network members.
|