Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

C Programming Language

how can i generate warnings for implicit casts that lose bits?


here is a post i put out (using Google Groups) that got dropped by
google:

i am using gcc as so:
$ gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
infodir=/usr/share/info --enable-shared --enable-threads=posix --
enable-checking=release --with-system-zlib --enable-__cxa_atexit --
disable-libunwind-exceptions --enable-libgcj-multifile --enable-
languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --
disable-dssi --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.1 20060525 (Red Hat 4.1.1-1)

and have compiled a simple test program (FILE: hello.c):

//
//   $ gcc -Wconversion -o hello hello.c
//   $ hello
//

#include <stdio.h>
main()
{
 unsigned long a_ulong = 0;          // 32 bit
 short a_short_array[128];            // 16 bit each

 a_ulong = 1234567;

 a_short_array[26] = a_ulong;

 printf("%d, %hx, %x, %lx \n", sizeof(a_short_array),
a_short_array[26], a_short_array[26], a_ulong );
//
// printf output is:
//
// 256, d687, ffffd687, 12d687
//

}

and ran it as so:

$ gcc -Wconversion -o hello hello.c
$ hello

getting output:

256, d687, ffffd687, 12d687

now, i have confirmed that a short is 16 bits and an unsigned long is
32 bits.  why does not this line of code:
      a_short_array[26] = a_ulong;
generate a warning when i have the -Wconversion or -Wall flags set on
the gcc invocation line?

there is clearly a loss of bits (or a changing of value).

here is what the manual says about it:
from http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options
:

-Wconversion
    Warn for implicit conversions that may alter a value. This
includes conversions between real and integer, like abs (x) when x is
double; conversions between signed and unsigned, like unsigned ui =
-1; and conversions to smaller types, like sqrtf (M_PI). Do not warn
for explicit casts like abs ((int) x) and ui = (unsigned) -1, or if
the value is not changed by the conversion like in abs (2.0). Warnings
about conversions between signed and unsigned integers can be disabled
by using -Wno-sign-conversion.

    For C++, also warn for conversions between NULL and non-pointer
types; confusing overload resolution for user-defined conversions; and
conversions that will never use a type conversion operator:
conversions to void, the same type, a base class or a reference to
them. Warnings about conversions between signed and unsigned integers
are disabled by default in C++ unless -Wsign-conversion is explicitly
enabled.

is there some other compiler flag i need to hit?  i don't get why this
doesn't generate a warning.
finally, please reply to both newsgroups as i don't hang around
comp.lang.c very much.

thank you,

r b-j

robert bristow-johnson <r@audioimagination.com> writes:
> [...]
> now, i have confirmed that a short is 16 bits and an unsigned long is
> 32 bits.  

How did you do that? Try this:

printf("size of short = %d, size of ulong = %d\n", sizeof(short), sizeof(unsigned long));

My suspicion is that they are both 32 bits (4 chars) on your machine
and that's why you're not getting a warning.

Robert, I NEVER use these data types anymore since I discovered
stdint.h defined in C99. I instead use explicit types like int16_t, uint32_t,
etc.
--
%  Randy Yates                  % "Remember the good old 1980's, when
%% Fuquay-Varina, NC            %  things were so uncomplicated?"
%%% 919-577-9882                % 'Ticket To The Moon'
%%%% <y@ieee.org>           % *Time*, Electric Light Orchestra
http://home.earthlink.net/~yatescr

Randy Yates <y@ieee.org> writes:
> robert bristow-johnson <r@audioimagination.com> writes:
>> [...]
>> now, i have confirmed that a short is 16 bits and an unsigned long is
>> 32 bits.  

> How did you do that? Try this:

> printf("size of short = %d, size of ulong = %d\n", sizeof(short), sizeof(unsigned long));

Doh! Sorry! I just reread your code and saw your statement verified there.

I have no freaking idea why the compiler doesn't burp. Not even with -Wall do I get
a warning on this conversion.
--
%  Randy Yates                  % "She's sweet on Wagner-I think she'd die for Beethoven.
%% Fuquay-Varina, NC            %  She love the way Puccini lays down a tune, and
%%% 919-577-9882                %  Verdi's always creepin' from her room."
%%%% <y@ieee.org>           % "Rockaria", *A New World Record*, ELO  
http://home.earthlink.net/~yatescr

Randy Yates wrote:

(snip)

> printf("size of short = %d, size of ulong = %d\n", sizeof(short), sizeof(unsigned long));

This makes the assumption that sizeof returns an int, when it
often returns something else.  Maybe you should also test
sizeof(sizeof(int))==sizeof(int)

-- glen

glen herrmannsfeldt wrote:
> Randy Yates wrote:

> (snip)

>> printf("size of short = %d, size of ulong = %d\n", sizeof(short),
>> sizeof(unsigned long));

> This makes the assumption that sizeof returns an int, when it
> often returns something else.  Maybe you should also test
> sizeof(sizeof(int))==sizeof(int)

This also makes the assumption that sizeof() returns size in bytes,
whereas sizeof returns the size in chars. Char may be bigger then one byte.

Vladimir Vassilevsky

DSP and Mixed Signal Design Consultant

http://www.abvolt.com

glen herrmannsfeldt <g@ugcs.caltech.edu> writes:
> This makes the assumption that sizeof returns an int, when it
> often returns something else.

sizeof's result is never an int, although it can be an unsigned
int.
--
Ben Pfaff
http://benpfaff.org

No, a "byte" is by definition the size of a char.  The term "byte" may
have other meanings outside the context of C, but sizeof(char) is 1 by
definition.

--
Keith Thompson (The_Other_Keith) k@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

glen herrmannsfeldt <g@ugcs.caltech.edu> writes:
> Randy Yates wrote:
> (snip)

>> printf("size of short = %d, size of ulong = %d\n", sizeof(short), sizeof(unsigned long));

> This makes the assumption that sizeof returns an int, when it
> often returns something else.  Maybe you should also test
> sizeof(sizeof(int))==sizeof(int)

No, just convert it before printing it:

    printf("size of short = %d, size of unsigned long = %d\n",
           (int)sizeof(short), (int)sizeof(unsigned long));

Or use "lu" and unsigned long if the result of sizeof might exceed
INT_MAX.

Or use "%zu" if your implementation supports it.

--
Keith Thompson (The_Other_Keith) k@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

Vladimir Vassilevsky <antispam_bo@hotmail.com> writes:
> This also makes the assumption that sizeof() returns size in bytes,
> whereas sizeof returns the size in chars. Char may be bigger then one
> byte.

This statement reflects some confusion about C definitions.  In
C, a char is always one byte, in that sizeof(char) is always 1.
However, the size of a byte is implementation-defined: it may be
larger than one octet (though not smaller).
--
"It wouldn't be a new C standard if it didn't give a
 new meaning to the word `static'."
--Peter Seebach on C99
On Jun 5, 11:39 pm, glen herrmannsfeldt <g@ugcs.caltech.edu> wrote:

> Randy Yates wrote:

> (snip)

> > printf("size of short = %d, size of ulong = %d\n", sizeof(short), sizeof(unsigned long));

> This makes the assumption that sizeof returns an int, when it
> often returns something else.

Perhaps it does, but on any realistic platform, why would this matter
if we're measuring the size of a short and a long?

--
Oli

In article <878xay6os3.@blp.benpfaff.org>,
Ben Pfaff  <b@cs.stanford.edu> wrote:

>However, the size of a byte is implementation-defined: it may be
>larger than one octet (though not smaller).

How big is an octet on ternary machines?

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.

In article <1181081659.289870.144@w5g2000hsg.googlegroups.com>,
Oli Charlesworth  <c@olifilth.co.uk> wrote:

>> > printf("size of short = %d, size of ulong = %d\n", sizeof(short),
>sizeof(unsigned long));
>> This makes the assumption that sizeof returns an int, when it
>> often returns something else.
>Perhaps it does, but on any realistic platform, why would this matter
>if we're measuring the size of a short and a long?

Because they're passed to a varargs function (printf), which will try
to access them as ints, so if they're in fact bigger than ints -
regardless of their value - things will go horribly wrong.

I don't think there is a simple reliable way to print a size_t in
general, since it could in principle be bigger than unsigned long
long, but in this case using (int)sizeof(short) would work.

-- Richard

--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.

Vladimir Vassilevsky <antispam_bo@hotmail.com> writes:
> glen herrmannsfeldt wrote:

>> Randy Yates wrote:
>> (snip)

>>> printf("size of short = %d, size of ulong = %d\n", sizeof(short),
>>> sizeof(unsigned long));
>> This makes the assumption that sizeof returns an int, when it
>> often returns something else.  Maybe you should also test
>> sizeof(sizeof(int))==sizeof(int)

> This also makes the assumption that sizeof() returns size in bytes,
> whereas sizeof returns the size in chars.

It is true that sizeof() returns the size in chars. It is also true
that in C, a char is, by definition, a byte.

However, even if you take "byte" to mean "8 bits," my statement was
not incorrect since Robert stated up front that the compiler was for
the i386, and that machine has 8-bit bytes.

I am aware of this "byte" definition since I ran into it on the TI TMS
C54x C compiler, where sizeof(int) = 1, even though an int is 16
bits. That machine's native datapath is 16 bits wide and incapable of
representing a type smaller than 16 bits.
--
%  Randy Yates                  % "She has an IQ of 1001, she has a jumpsuit
%% Fuquay-Varina, NC            %            on, and she's also a telephone."
%%% 919-577-9882                %
%%%% <y@ieee.org>           %        'Yours Truly, 2095', *Time*, ELO  
http://home.earthlink.net/~yatescr

That brings up an interesting question: Doesn't this behavior depend
on the machine's endianness?

For example, consider the statement

  printf("sizeof(int) = %d", sizeof(int));

and the case in which int is 16 bits and sizeof() returns 32 bits.

Is it true that a little-endian machine will print this correctly,
while a big-endian machine will not?
--
%  Randy Yates                  % "She's sweet on Wagner-I think she'd die for Beethoven.
%% Fuquay-Varina, NC            %  She love the way Puccini lays down a tune, and
%%% 919-577-9882                %  Verdi's always creepin' from her room."
%%%% <y@ieee.org>           % "Rockaria", *A New World Record*, ELO  
http://home.earthlink.net/~yatescr

In article <m3odjuc93d.@ieee.org>, Randy Yates  <y@ieee.org> wrote:

>For example, consider the statement

>  printf("sizeof(int) = %d", sizeof(int));

>and the case in which int is 16 bits and sizeof() returns 32 bits.

>Is it true that a little-endian machine will print this correctly,
>while a big-endian machine will not?

For a common method of implementation, yes.  If you printed two values
the second would print as zero.

But varargs implementations can be more complicated.  They could use
separate arrays for arguments of different types, in which case they
would look in completely the wrong place for the argument.

They could also pass some arguments in registers, in which case it
might work regardless of endianness, or always fail.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.

Richard Tobin said:

> In article <878xay6os3.@blp.benpfaff.org>,
> Ben Pfaff  <b@cs.stanford.edu> wrote:

>>However, the size of a byte is implementation-defined: it may be
>>larger than one octet (though not smaller).

> How big is an octet on ternary machines?

The requirement is to be able to represent at least 256 discrete values.
This can be accomplished in six trits, the relevant trit pattern being
100110.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.

Ben Pfaff wrote:
> glen herrmannsfeldt <g@ugcs.caltech.edu> writes:
>>This makes the assumption that sizeof returns an int, when it
>>often returns something else.
> sizeof's result is never an int, although it can be an unsigned
> int.

So I should have said "always" instead of "often"?

-- glen

Vladimir Vassilevsky wrote:

(even more snip)

>>> printf("size of short = %d, size of ulong = %d\n", sizeof(short),
>>> sizeof(unsigned long));
>> This makes the assumption that sizeof returns an int, when it
>> often returns something else.  Maybe you should also test
>> sizeof(sizeof(int))==sizeof(int)
> This also makes the assumption that sizeof() returns size in bytes,
> whereas sizeof returns the size in chars. Char may be bigger then one byte.

I would say it is the reader of the output that makes that
assumption, not the program.  If you write:

  printf("sizeof(short) = %d, sizeof(unsigned long) = %d\n",
      (int)sizeof(short), (int)sizeof(unsigned long));

then it is more obvious that it is returning the result
of sizeof.

-- glen

In article <582dnQ-CT9LncPjbnZ2dnUVZ8qaqn@bt.com>,
Richard Heathfield  <r@see.sig.invalid> wrote:

>>>However, the size of a byte is implementation-defined: it may be
>>>larger than one octet (though not smaller).
>> How big is an octet on ternary machines?
>The requirement is to be able to represent at least 256 discrete values.
>This can be accomplished in six trits, the relevant trit pattern being
>100110.

What I was getting at was whether the definition of octet should be
taken to be 8 bits, or 8 whatsits (where whatsit = bit, trit, etc).
That is, can a six-trit word be considered to be smaller than an
octet, defeating the claim that a byte may not be smaller than octet?

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.

Richard Tobin said:

> In article <582dnQ-CT9LncPjbnZ2dnUVZ8qaqn@bt.com>,
> Richard Heathfield  <r@see.sig.invalid> wrote:

>>>>However, the size of a byte is implementation-defined: it may be
>>>>larger than one octet (though not smaller).

>>> How big is an octet on ternary machines?

>>The requirement is to be able to represent at least 256 discrete
>>values. This can be accomplished in six trits, the relevant trit
>>pattern being 100110.

> What I was getting at was whether the definition of octet should be
> taken to be 8 bits, or 8 whatsits (where whatsit = bit, trit, etc).

Oh, I see.

> That is, can a six-trit word be considered to be smaller than an
> octet, defeating the claim that a byte may not be smaller than octet?

The C Standard makes no such claim. It only makes the claim that a byte
must be at least 8 bits wide. If we accept the possibility of a ternary
machine, the minimum number of trits that would do the trick is 6.

As far as I can tell, the word 'octet' doesn't appear in the Standard.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.

Randy Yates wrote:

(snip)

>>I don't think there is a simple reliable way to print a size_t in
>>general, since it could in principle be bigger than unsigned long
>>long, but in this case using (int)sizeof(short) would work.

As someone else mentioned, %zu has been added to solve the problem.

> That brings up an interesting question: Doesn't this behavior depend
> on the machine's endianness?
> For example, consider the statement
>   printf("sizeof(int) = %d", sizeof(int));
> and the case in which int is 16 bits and sizeof() returns 32 bits.
> Is it true that a little-endian machine will print this correctly,
> while a big-endian machine will not?

It is reasonably likely that it will, though it is still wrong.
Also, that will only work if you are just printing one of them.

I consider this a disadvantage of little-endian, as it tends to
hide bugs due to type mismatch until it is too late.
Consider also the mistake of printing a 16 bit value with a
format item expecting 32 bits.  (or any function expecting
a 32 bit value.)  It might work.

-- glen

grumble, grumble...

okay guys we can argue a little bit about the sizes of types, but
isn't it clear that when i run these lines of code:

 a_ulong = 1234567;

 a_short_array[26] = a_ulong;

 printf("%d, %hx, %x, %lx \n", sizeof(a_short_array),
a_short_array[26], a_short_array[26], a_ulong );

and get this for output:

256, d687, ffffd687, 12d687

that the bits in the hex digits "12" went bye-bye in the assignment
statement?  i just wanna know what flag to set (if any) that makes the
compiler tell me i might want to check the statement that could
potentially throw away those bits.  i would think, from the
description that -Wconversion or -Wall should do it, but it doesn't
and i was wondering if the hardcore C or gcc geeks might know the
magic invocation to generate such a warning.

i'm no linux or gnu freak (really a neophyte), i just remember in my
old codewarrior days that there was a nice little check box i could
hit to see such warnings.  killing such warnings is a useful
discipline to have to avoid some unforseen bugs that might also be
hard to find.  it's sorta like enforcing strict type checking.

r b-j

In article <c9GdnRrzH9jRb_jbnZ2dnUVZ_segn@comcast.com>,
glen herrmannsfeldt  <g@ugcs.caltech.edu> wrote:

>As someone else mentioned, %zu has been added to solve the problem.

I'd never noticed that before.  Nor had I noticed %jd and %td.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.

rich@cogsci.ed.ac.uk (Richard Tobin) writes:
> In article <878xay6os3.@blp.benpfaff.org>,
> Ben Pfaff  <b@cs.stanford.edu> wrote:
>>However, the size of a byte is implementation-defined: it may be
>>larger than one octet (though not smaller).

> How big is an octet on ternary machines?

An "octet" is by definition 8 bits.  If you don't have bits, you can't
have octets.  Of course a ternary machine can emulate bits; the answer
to your question then depends on how the emulation is done.

If you use ternary machines, it might be reasonable to refer to a
collection of 8 trits as an "octet".  That would conflict with normal
usage, but then so do ternary machines.

--
Keith Thompson (The_Other_Keith) k@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

robert bristow-johnson wrote:

(snip)

> that the bits in the hex digits "12" went bye-bye in the assignment
> statement?  i just wanna know what flag to set (if any) that makes the
> compiler tell me i might want to check the statement that could
> potentially throw away those bits.  i would think, from the
> description that -Wconversion or -Wall should do it, but it doesn't
> and i was wondering if the hardcore C or gcc geeks might know the
> magic invocation to generate such a warning.

As far as I know, this is part of C.

Note that Java requires a cast for all narrowing conversions.
Maybe you should switch to Java instead.

-- glen

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc