Subj : Re: Any help on why? To : borland.public.cpp.borlandcpp From : waking Date : Sun Jul 11 2004 01:55 am On Thu, 08 Jul 2004 18:58:29 -0700, Bob Gonder wrote: >>Again a misuse of specifiers. "L" is intended for use with long doubles, > >Only when applied to float formats. for integer formats including X, >it is long long (or int64) As I previously stated: only in compilers which support it. The OP wants to target 16-bit embedded systems. No 16-bit compiler I know of supports long long or __int64. >See yourself. L is 64 bits for int formats, not 80. Not in any 16-bit compiler which the OP is likely to use. >>The parser can distinguish an integer from a float type. It's looking >>at the source code, not the stack. > >The Compiler Parser? I've yet to see a compiler do anything other than >pass the string to the RTL. The compiler may do anything it pleases with it. Stay tuned. >>X is specifically intended for use with ints. If you pass a float to it the >>parser can detect that. (As shown in the warnings from CLint++.) > >LINT ISN'T A C COMPLIER! Actually, it complies quite nicely. ;-) >The C Compiler DOESN'T KNOW OR CARE! Wrong again. The C compiler's parser can detect anything which a Lint program can, and some do. According to your "theory", the compiler doesn't know or care as long as the arg and the specifiers are the same size. Even then, according to you, the compiler doesn't "care". It just passes whatever you give it, and if the sizes happily happen to coincide the results will be kosher. A float is 32 bits. A long int is 32 bits. According to you, it doesn't matter what you pass. According to you, you can use %ld, %lX or %X with float args. Let's see what happens when we try that using some C compilers. ======================================================== Test program: #include int main() { double num = 3.14159265358979323846F; printf("sizeof(long double) = %u\n", sizeof(long double)); printf("sizeof(double) = %u\n", sizeof(double)); printf("sizeof(float) = %u\n", sizeof(float)); printf("sizeof(long) = %u\n", sizeof(long)); printf("Using \"%%f\\t%%f\\t%%lX\" gives: "); printf("%f\t%f\t%lX\n", 1.5, 1.5, 1.5); /* line 13 */ printf("Using \"%%f\\t%%lX\\t%%f\" gives: "); printf("%f\t%lX\t%f\n", 1.5, 1.5, 1.5); /* line 16 */ printf("Using \"%%lX\\t%%f\\t%%f\" gives: "); printf("%lX\t%f\t%f\n", 1.5, 1.5, 1.5); /* line 18 */ printf("Using \"%%f\\t%%f\\t%%lX\" gives: "); printf("%f\t%f\t%lX\n", num, num, num); /* line 22 */ printf("Using \"%%f\\t%%lX\\t%%f\" gives: "); printf("%f\t%lX\t%f\n", num, num, num); /* line 25 */ printf("Using \"%%lX\\t%%f\\t%%f\" gives: "); printf("%lX\t%f\t%f\n", num, num, num); /* line 28 */ printf("Using \"%%X\\t%%f\\t%%f\" gives: "); printf("%X\t%f\t%f\n", num, num, num); /* line 31 */ printf("Using \"%%ld\\t%%f\\t%%f\" gives: "); printf("%ld\t%f\t%f\n", num, num, num); /* line 34 */ return 0; } ======================================================== Using Pacific C v.7.51 (http://www.hitech.com.au) Messages: long argument required (warning) <<-- line 13, 3rd arg long argument required (warning) <<-- line 16, 2nd arg long argument required (warning) <<-- line 19, 1st arg long argument required (warning) <<-- line 22, 3rd arg long argument required (warning) <<-- line 25, 2nd arg long argument required (warning) <<-- line 28, 1st arg integral argument required (warning) <<-- line 31, 1st arg long argument required (warning) <<-- line 34, 1st arg Help: - Error explanation: long argument required ---- A long argument is required for this format specifier. Check the number and order of format specifiers and corresponding arguments. - Error explanation: integral argument required --- An integral argument is required for this format specifier. Check the number and order of format specifiers and corresponding arguments. ======================================================== Note that in both cases the message from the compiler says "required", not "recommended". Note that the compiler implementors "cared" enough to include the check(s) in the parser. Note that the compiler "knew" that a mismatch was being attempted. ======================================================== Output when program is run (wrapped manually): sizeof(long double) = 8 sizeof(double) = 8 sizeof(float) = 4 sizeof(long) = 4 Using "%f\t%f\t%lX" gives: 1.500000 1.500000 0 Using "%f\t%lX\t%f" gives: 1.500000 0 0.000000 Using "%lX\t%f\t%f" gives: 0 0.000000 0.000000 Using "%f\t%f\t%lX" gives: 3.141593 3.141593 54442D1A Using "%f\t%lX\t%f" gives: 3.141593 54442D1A 861921254984563017000000 000000000000000000000000000000000000000000000000000000000000000000000 00000.000000 Using "%lX\t%f\t%f" gives: 54442D1A 861921254984563017000000000000000 00000000000000000000000000000000000000000000000000000000000000000.000 000 861921254984563017000000000000000000000000000000000000000000000 00000000000000000000000000000000000.000000 Using "%X\t%f\t%f" gives: 2D1A 0.000000 0.000000 Using "%ld\t%f\t%f" gives: 1413754138 86192125498456301700000000000 000000000000000000000000000000000000000000000000000000000000000000000 ..000000 86192125498456301700000000000000000000000000000000000000000 000000000000000000000000000000000000000.000000 ======================================================== Note the effect on subsequent (left to right) arguments when an incorrect type specifier is encountered. Are the displayed values those which you expected? ======================================================== This compiler also flags %lf when used with printf, giving the message: error in format string (warning) Help: - Error explanation: error in format string --- There is an error in the format string here. The string has been interpreted as a printf() style format string, and it is not syntactically correct. If not corrected, this will cause unexpected behaviour at run time. ======================================================== Note the phrases "not syntactically correct" and "this will cause unexpected behaviour at run time." ======================================================== It also flags mismatches between the number of format specifers and arguments supplied, as these examples show: printf("\t%f\t%f\n", num, num, num); too many arguments for format string (warning) - Error explanation: too many arguments for format string - There are too many arguments for this format string. This is harmless, but may represent an incorrect format string. printf("%f\t%f\t%f\n", num, num); too few arguments for format string (warning) - Error explanation: too few arguments for format string - There are too few arguments for this format string. This would result in a garbage value being printed or converted at run time. ======================================================== Again note that it is the *source code* being parsed by the *compiler*, something which you claim is never done. Note also the consequences for ignoring some of these "warnings", as shown by the last example. You are free to ignore syntax if you choose. You are also free to ignore traffic lights and railway crossing barriers. ======================================================== DJGPP (32-bit DOS target - DPMI32) also notes the mismatches when it parses the source: (http://www.delorie.com/djgpp/) reptest.c(13) Warning: long unsigned int format, double arg (arg 4) reptest.c(16) Warning: long unsigned int format, double arg (arg 3) reptest.c(19) Warning: long unsigned int format, double arg (arg 2) reptest.c(22) Warning: long unsigned int format, double arg (arg 4) reptest.c(25) Warning: long unsigned int format, double arg (arg 3) reptest.c(28) Warning: long unsigned int format, double arg (arg 2) reptest.c(31) Warning: unsigned int format, double arg (arg 2) reptest.c(34) Warning: long int format, double arg (arg 2) If %LX is used (suggesting a long long integer type) as in: printf("%f\t%f\t%LX\n", 1.5, 1.5, 1.5); /* line 13 */ the compiler issues this message: reptest.c(13) Warning: long long unsigned int format, double arg (arg 4) It seems these compiler implementors also felt it worthwhile to detect such mismatches when *parsing* the *source* code. ======================================================== >If the compiler doesn't do what I tell it to do, then it is broken. Not if what you tell it to do violates the rules of the language. Then you're broken. >It can't decide on it's own that it knows what's good >for the program(mer). It does it all the time by optimizing code. e.g. - Omitting "dead' code, using prefix operators when the programmer specified post-fix (e.g. ++x instead of x++), merging strings, inlining or not inlining contrary to the programmer's source code, unrolling loops, using or not using registers when it decides to supply what the programmer omitted or omit what he/she supplied, etc. It can decide (quite rightly) to enforce the rules of the language, and to penalize programming anarchists who can't adapt. You don't seem to have accepted the realities of programming with anything other than a 1st-generation language. Disregarding the rules of syntax and grammar in HLLs can have catastrophic effects. Granted C is more like a 2nd-GL than a 3rd, it nonetheless *does* have requirements which are imposed on the programmer. You're free to disregard them if you please, and accept the consequences. No "language police" will come knocking at midnight. (Unless I find their phone number.) ;-) -- Wayne A. King (waking@idirect.com, Wayne_A_King@compuserve.com) .