C99, strict aliasing

M

Mike

Is the following legal in C99?
Does it violate strict aliasing?

int func(int arg)
{
union {
int i;
char c[sizeof(int)];
} u;
u.i=arg;
scribble(u.c);
return u.i;
}
I've found hints that it is,
but nothing I'm sure of.
 
B

Ben Bacarisse

Mike said:
Is the following legal in C99?
Does it violate strict aliasing?

int func(int arg)
{
union {
int i;
char c[sizeof(int)];
} u;
u.i=arg;
scribble(u.c);
return u.i;
}
I've found hints that it is,
but nothing I'm sure of.

It's fine, at least as far as the part that seems to be bothering you is
concerned (the aliasing). One weird machines, scribble(u.c) can produce
a trap representation in u.i, but presumably you are doing this
*because* you want to fiddle with the representation and you know what
you are doing. It might be worth saying what your top-level goal is:
i.e. to what problem is the above union a solution? There may be other
well-known solutions.

Elsewhere in this thread (with so much quoted text that I stopped
reading it) I saw you bring up the issues of using an array of floats
instead of chars. Maybe you could say, here, why you want to do that
since it seems like quite another kind of use for a union. Again,
aliasing is not so much the problem as messing about with complex
representations.
 
M

Mike

Mike said:
Is the following legal in C99?
Does it violate strict aliasing?
int func(int arg)
{
union {
    int i;
    char c[sizeof(int)];
} u;
u.i=arg;
scribble(u.c);
return u.i;
}
I've found hints that it is,
but nothing I'm sure of.

It's fine, at least as far as the part that seems to be bothering you is
concerned (the aliasing).  One weird machines, scribble(u.c) can produce
a trap representation in u.i, but presumably you are doing this

Are trap ints really allowed in C?
*because* you want to fiddle with the representation and you know what
you are doing.  It might be worth saying what your top-level goal is:
i.e. to what problem is the above union a solution?  There may be other
well-known solutions.

I know of another solution, but avr-gcc produces awful code for it.
The code I've given is fairly standard procedure for manipulating the
bytes of an int.
It pretty much always works.
I'm trying to discover what C99 actually requires of such code.
If it's undefined behavior, updating a compiler could cause it to fail
without warning.
If it's unspecified behavior, then if it works once,
I would expect it to continue work until a change in the
representation of an int.
As a bonus, the compiler wouldn't complain about it.
Elsewhere in this thread (with so much quoted text that I stopped
reading it) I saw you bring up the issues of using an array of floats
instead of chars.  Maybe you could say, here, why you want to do that
since it seems like quite another kind of use for a union.  Again,
aliasing is not so much the problem as messing about with complex
representations.

I don't want to use floats.
It was just an example for which I knew the answer and demonstrated my
reason for concern.
In the float example, if scribble changed u.c,
the compiler would be allowed to return 0 or drown my brother-in-law
in nasal demons.

In some situations, chars are a special case,
but I'm unclear on what situations those are.
 
B

Ben Bacarisse

Mike said:
Mike said:
Is the following legal in C99?
Does it violate strict aliasing?
int func(int arg)
{
union {
    int i;
    char c[sizeof(int)];
} u;
u.i=arg;
scribble(u.c);
return u.i;
}
I've found hints that it is,
but nothing I'm sure of.

It's fine, at least as far as the part that seems to be bothering you is
concerned (the aliasing).  One weird machines, scribble(u.c) can produce
a trap representation in u.i, but presumably you are doing this

Are trap ints really allowed in C?

Yes. int can have padding bits and some settings of these could be trap
representations. But there is another possible trap representation with
no padding bits: sign bit one and all others zero for 2's complement
and sign and magnitude representations; or all bits one for 1's
complement systems. This does not have to be a trap, but it is
permitted, presumably because it is/was one on some machines.
I know of another solution, but avr-gcc produces awful code for it.
The code I've given is fairly standard procedure for manipulating the
bytes of an int.
It pretty much always works.
I'm trying to discover what C99 actually requires of such code.

It does what you think is does and C99 says that is does that. Any
problems would come from peculiar architectures such as ints with trap
representations or ones in which char has padding bits that don't
correspond to padding bits in the int. I don't know of any -- I am
just speculating.

Using unsigned char is safer since it can't have any padding bits.

By the way, you don't need the union:

int i = arg;
scribble((unsigned char *)&i);
return i;

will also work.

In some situations, chars are a special case,
but I'm unclear on what situations those are.

Yes. I don't fany trying to list them all, but for your purposes
special permission is granted to access an object as an array of (signed
or unsigned) char -- which is why the direct method with no union is
often used.
 
T

Tim Rentsch

Mike said:
Is the following legal in C99?
Does it violate strict aliasing?

int func(int arg)
{
union {
int i;
char c[sizeof(int)];
} u;
u.i=arg;
scribble(u.c);
return u.i;
}
I've found hints that it is,
but nothing I'm sure of.

It's legal. I believe it would still be legal even if the type of
'c' were a non-character type (e.g., double). In both cases the
result depends on implementation-defined information (in particular
the representations of types involved), and so could result in UB
because of a trap representation, but other than that there is no
undefined behavior here.

Unfortunately it's not clear (at least not to me) whether this
example violates GCC strict aliasing. The gcc man page contains
some examples, but it's hard to say which side of the line this
example is supposed to fall on. Here 'c' being an array of
character type may very well make a difference. It would be
nice if the GCC people provided unambiguous documentation on
this (which in fact they may very well do, but I'm not aware
of it if so).
 
T

Tim Rentsch

Mike said:
Mike said:
Is the following legal in C99?
Does it violate strict aliasing?
int func(int arg)
{
union {
int i;
char c[sizeof(int)];
} u;
u.i=arg;
scribble(u.c);
return u.i;
}
I've found hints that it is,
but nothing I'm sure of.

[... question about making u.c be float instead of char ...]

I don't want to use floats.
It was just an example for which I knew the answer and demonstrated my
reason for concern.
In the float example, if scribble changed u.c,
the compiler would be allowed to return 0 or drown my brother-in-law
in nasal demons.

Which section(s) of the Standard lead you to think that?
 

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

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top