Question about warning

  • Thread starter =?ISO-8859-1?Q?Daniel_Sj=F6blom?=
  • Start date
?

=?ISO-8859-1?Q?Daniel_Sj=F6blom?=

When I compile this (with GCC and optimizations on):

void foo(void)
{
int a;
float f = *((float *) &a);
}

I get the warning : "dereferencing type-punned pointer will break
strict-aliasing rules". Does this mean that f and a can be stored in the
same memory location?
 
M

Malcolm

Daniel Sjöblom said:
When I compile this (with GCC and optimizations on):

void foo(void)
{
int a;
float f = *((float *) &a);
}

I get the warning : "dereferencing type-punned pointer will break
strict-aliasing rules". Does this mean that f and a can be stored in the
same memory location?
No. A compiler is allowed to warn about anything it likes (so a
sophisticated compiler could warn about British spelling in a function
called setcolour(), for example).
Your function is fairly useless in well-designed code, because a bitwise
reinterpretation of an integer as a float is non-portable, not human
meaningful, and not something you should need to do (though in practise you
might need to do it, for instance to speed up the floating point operations
by twiddling bits directly). So the compiler warns about it.
 
J

Jack Klein

When I compile this (with GCC and optimizations on):

void foo(void)
{
int a;
float f = *((float *) &a);
}

I get the warning : "dereferencing type-punned pointer will break
strict-aliasing rules". Does this mean that f and a can be stored in the
same memory location?

It means that this code produces undefined behavior. You have broken
the rules, and the C standard no longer places any requirements on the
result. Anything that happens when this code is executed, or even
compiled, is beyond the scope of the C language.
 
J

jota

Hello!
I dont know what u want to achive with the code but my guess would be that
u want to cast whatever value 'a' has to
'f'. (converting int to float)
Like
---------------
void foo(void)
{
int a;
float f = (float)a;
}
 
C

Chris Torek

No. A compiler is allowed to warn about anything it likes (so a
sophisticated compiler could warn about British spelling in a function
called setcolour(), for example).

True, but irrelevant in this case.
Your function is fairly useless in well-designed code, because a bitwise
reinterpretation of an integer as a float is non-portable ...

More importantly, in future versions of gcc (and perhaps even current
versions on certain machines), the code above will not even achieve
its intent:
... not something you should need to do (though in practise you
might need to do it, for instance to speed up the floating point operations
by twiddling bits directly). So the compiler warns about it.

In particular, the "bit twiddling" via sharing of underlying storage
simply WILL NOT HAPPEN (under some circumstances), because the C
standards say the compiler is allowed to assume that it DOES not
happen. In order to "bit-twiddle" a float in C, you need to use
a character type -- "unsigned char" is best -- to access its
individual bytes.

The exact circumstances under which gcc will (or might) optimize
away the desired bit-twiddling are hard to describe, but the C
standards always allow it, hence the warning.
 
M

Malcolm

Chris Torek said:
In particular, the "bit twiddling" via sharing of underlying storage
simply WILL NOT HAPPEN (under some circumstances), because the > C
standards say the compiler is allowed to assume that it DOES not
happen. In order to "bit-twiddle" a float in C, you need to use
a character type -- "unsigned char" is best -- to access its
individual bytes.
So

int samesign(float x, float y)
{
return ((*(int *)&x ^ *(int *)&y) & SIGNBIT) ? 0 : 1;
}

is not OK (SIGNBIT is a constant with the float sign set)

int samesign(float x, float y)
{
return (*((unsigned char *)&x +1)^ *((unsigned char*)&y + 1) & SIGNBIT_CH
? 0 : 1;
}

is OK, assuming a bit unrealistically that the sign is in the second byte of
the float.
 
J

Jack Klein

standards say the compiler is allowed to assume that it DOES not
So

int samesign(float x, float y)
{
return ((*(int *)&x ^ *(int *)&y) & SIGNBIT) ? 0 : 1;
}

is not OK (SIGNBIT is a constant with the float sign set)

int samesign(float x, float y)
{
return (*((unsigned char *)&x +1)^ *((unsigned char*)&y + 1) & SIGNBIT_CH
? 0 : 1;
}

is OK, assuming a bit unrealistically that the sign is in the second byte of
the float.

It is in the sense that it is not undefined behavior. Any area of
memory that your program has the right to read may be read as an array
of unsigned chars. They are unique in C in that they have no trap or
error representations, every possible combination of bits represents a
valid value.

Whether it is wise to do this is another story. Assuming it works on
a particular implementation, it is hideously non-portable to other
implementations.
 
B

Barry Schwarz

When I compile this (with GCC and optimizations on):

void foo(void)
{
int a;
float f = *((float *) &a);
}

I get the warning : "dereferencing type-punned pointer will break
strict-aliasing rules". Does this mean that f and a can be stored in the
same memory location?

What your compiler is trying to tell you is that if you use the
address of a as the address of a floating point variable, it is
possible that

You will have an alignment problem which will prevent the code
from working. It is possible that a properly aligned int does not
satisfy the alignment for a float.

You will have a value problem when you dereference the address
which will prevent the code from working. It is possible that the bit
pattern in the int is not a valid bit pattern for a float. (Your
current code has undefined behavior anyway since a is not initialized
but you attempt to evaluate it. The situation described applies if a
is initialized.)


<<Remove the del for email>>
 
?

=?ISO-8859-1?Q?Daniel_Sj=F6blom?=

Chris said:
More importantly, in future versions of gcc (and perhaps even current
versions on certain machines), the code above will not even achieve
its intent:




In particular, the "bit twiddling" via sharing of underlying storage
simply WILL NOT HAPPEN (under some circumstances), because the C
standards say the compiler is allowed to assume that it DOES not
happen. In order to "bit-twiddle" a float in C, you need to use
a character type -- "unsigned char" is best -- to access its
individual bytes.

The exact circumstances under which gcc will (or might) optimize
away the desired bit-twiddling are hard to describe, but the C
standards always allow it, hence the warning.

I knew that dereferencing a cast pointer can cause traps if the address
is not properly aligned for the cast to type. But are you saying that
the compiler can reorder the instructions so that the bits of the float
can be just about any value the int has at some point (assuming no
alignment problems)? Does this also mean that the compiler cannot safely
reorder stores/loads to/from any char pointer?

Thanks to everyone who responded.
 
D

Dan Pop

In said:
Whether it is wise to do this is another story. Assuming it works on
a particular implementation, it is hideously non-portable to other
implementations.

OTOH, if one resorts to such a thing, it is because the portable version
is hideously slow on that implementation and the performance difference
does matter to the overall program performance.

Real life programming constraints are more complex than "portable code:
good, non-portable code: bad".

Dan
 
D

Dan Pop

In said:
When I compile this (with GCC and optimizations on):

void foo(void)
{
int a;
float f = *((float *) &a);
}

I get the warning : "dereferencing type-punned pointer will break
strict-aliasing rules". Does this mean that f and a can be stored in the
same memory location?

Nope, it means that you're trying to access a memory area using another
type than the one used in the declaration of the object occupying that
area. Sometimes, this is allowed, but in the general case this results
in undefined behaviour. Here's the exact text of the standard:

7 An object shall have its stored value accessed only by an lvalue
expression that has one of the following types:73)

- a type compatible with the effective type of the object,

- a qualified version of a type compatible with the effective
type of the object,

- a type that is the signed or unsigned type corresponding to
the effective type of the object,

- a type that is the signed or unsigned type corresponding to
a qualified version of the effective type of the object,

- an aggregate or union type that includes one of the
aforementioned types among its members (including, recursively,
a member of a subaggregate or contained union), or

- a character type.
____________________

73) The intent of this list is to specify those circumstances
in which an object may or may not be aliased.

Dan
 
J

Jack Klein

OTOH, if one resorts to such a thing, it is because the portable version
is hideously slow on that implementation and the performance difference
does matter to the overall program performance.

Real life programming constraints are more complex than "portable code:
good, non-portable code: bad".

Dan

You do seem to have a problem reading the actual words that I write
before you respond to them.

Where in my original post did I say that non-portable code was bad?

In fact where did I imply any judgment at all?

How do you read this sentence "Whether it is wise to do this is
another story." as implying that it is or is not wise? It prefaces a
warning about the portability issue, nothing more.
 
D

Dan Pop

In said:
You do seem to have a problem reading the actual words that I write
before you respond to them.

Relax, no such problems.
Where in my original post did I say that non-portable code was bad?

In fact where did I imply any judgment at all?

How do you read this sentence "Whether it is wise to do this is
another story." as implying that it is or is not wise? It prefaces a
warning about the portability issue, nothing more.

A useless warning about the portability issue, because its author pointed
it out himself:

is OK, assuming a bit unrealistically that the sign is in the second
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
byte of the float.

So, assuming *you* can read the text you're commenting upon, what was the
point of your own comments? Everyone, *including the author*, knew, that
the example was non portable and that it served a completely different
purpose: to verify if its author got the aliasing rules right.

Therefore, your comments could be *meaningfully* interpreted *only* in a
pejorative key.

Dan
 

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,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top