|
|
 |
 |
 |
 |
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
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. Char may be bigger then one > byte.
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
rich @cogsci.ed.ac.uk (Richard Tobin) writes: > 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.
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
|
 |
 |
 |
 |
|