gtchen@faline.bellcore.com (George T. Chen) (09/11/87)
Has anyone had this problem? ... void get_value(size) long *size; { ...(do some processing)... printf("%ld",*size); } void routine() { ...(some declarations)... long size; ...(some other stuff).... get_value(&size); printf("%ld",size); } This routine dies on me! (Well not dies but doesn't work) For some reason, size is correct in the get_value routine, but seems to be int(size/256.)*256 in the calling routine. Almost as if the least significant byte became 0. However, if I now change routine to void routine() { ...(same declarations)... long garbage,size; ...(same other stuff).... get_value(&size); printf("%ld",size); garbage = 0; /* So that garbage is allocated memory instead */ /* of being ignored by the compiler */ } then everything works fine and dandy. What's going on? Someone told me it might be a problem with odd and even bytes, but I don't quite understand that. All help appreciated. -- +-----------------------------------------------------------------------------+ |What's a .signature? Life is an equation whose only solutions are irrational | |gtchen@thumper.bellcore.com ! gtchen@romeo.caltech.edu ! gtchen@where.am.i?. | +-----------------------------------------------------------------------------+
moss@BRL.ARPA (Gary S. Moss (SLCBR-VL-V)) (09/14/87)
George, The format %ld is wrong when using the PRINTF family of functions. The reason for this is that integer arguments are *always* widened to LONG when passed in to a function, so the %d format is meant for LONGS. This is also true for %f. I am not certain, but pretty sure that I have gotten wrong behavior when using %ld in this context on certain hardware. This is contrary to the SCANF family where you *need* the %ld because you are placing the result in an address whose type is not known to the function. ~moss
ark@alice.UUCP (09/14/87)
In article <9266@brl-adm.ARPA>, moss@BRL.ARPA writes: > The format %ld is wrong when using the PRINTF family of functions. > The reason for this is that integer arguments are *always* widened to LONG > when passed in to a function, so the %d format is meant for LONGS. This > is also true for %f. I am not certain, but pretty sure that I have gotten > wrong behavior when using %ld in this context on certain hardware. Nope. Chars and shorts are widened to ints, and floats are widened to doubles, but ints are not widened to longs. Thus you should always use %d for char, short, or int, and %ld for long.
guy@sun.uucp (Guy Harris) (09/15/87)
> The format %ld is wrong when using the PRINTF family of functions. > The reason for this is that integer arguments are *always* widened to LONG > when passed in to a function, so the %d format is meant for LONGS. Excuse me, but this is total rubbish. Arguments *shorter* than "int" are widened to "int" - NOT "long" - when passed to a function. "int" arguments are left alone. "%d" will NOT work for "long" arguments on a machine where "int" and "long" are not the same size. %d is NOT meant for "long"s, it is meant for "int"s. "%ld" is what you must use for "long"s. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com (or guy@sun.arpa)
aeusesef@csun.UUCP (Sean Eric Fagan) (09/15/87)
In article <9266@brl-adm.ARPA> moss@BRL.ARPA (Gary S. Moss (SLCBR-VL-V)) writes: >George, > The format %ld is wrong when using the PRINTF family of functions. >The reason for this is that integer arguments are *always* widened to LONG >when passed in to a function, so the %d format is meant for LONGS. This >is also true for %f. I am not certain, but pretty sure that I have gotten >wrong behavior when using %ld in this context on certain hardware. > >~moss Uhm, I think you're going to get a lot of flack about this, so I'll start it. C does *NOT* convert integer arguments to longs unless a)told to (via (long) typecast or a 'L' at the end of the suffix) or b)needs to because it is used in an expression where one of the subexpressions is a long (did that make sense?). Remember, this all comes from a PDP-11, where having longs meant extra work for the cpu. Floats are, however, converted to doubles. Of course, I could be wrong, but I don't believe so. ----- Sean Eric Fagan Office of Computing/Communications Resources (213) 852 5742 Suite 2600 1GTLSEF@CALSTATE.BITNET 5670 Wilshire Boulevard Los Angeles, CA 90036 {litvax, rdlvax, psivax, hplabs, ihnp4}!csun!aeusesef "Tempus fugit AirCal"
henry@utzoo.UUCP (Henry Spencer) (09/15/87)
> The format %ld is wrong when using the PRINTF family of functions. > The reason for this is that integer arguments are *always* widened to LONG > when passed in to a function, so the %d format is meant for LONGS. NO NO NO NO NO!!!! Arguments of type short or int are passed as int , not as long! On 32-bit machines, it usually happens that "int" and "long" are synonymous. But this is not guaranteed to be true everywhere! %d is the correct format for shorts and ints in printf; %ld should always be used for longs. In scanf, it's %hd for short, %d for int, %ld for long, no mistakes allowed. > This is also true for %f. Here we have slightly different rules: floats are passed as doubles, so in printf it is always correct to use %f. In scanf, once again, it is necessary to be fussier: %f for float and %lf for double. The ANSI C people have added some minor complications to this but have not changed the basic rules. If code that follows these rules malfunctions, either the code or the compiler (or its library) is broken. -- "There's a lot more to do in space | Henry Spencer @ U of Toronto Zoology than sending people to Mars." --Bova | {allegra,ihnp4,decvax,utai}!utzoo!henry
pinkas@cadeos.UUCP (09/15/87)
In article <9266@brl-adm.ARPA> moss@BRL.ARPA (Gary S. Moss (SLCBR-VL-V)) writes: >George, > The format %ld is wrong when using the PRINTF family of functions. >The reason for this is that integer arguments are *always* widened to LONG >when passed in to a function, so the %d format is meant for LONGS. This >is also true for %f. I am not certain, but pretty sure that I have gotten >wrong behavior when using %ld in this context on certain hardware. > > This is contrary to the SCANF family where you *need* the %ld because >you are placing the result in an address whose type is not known to the >function. > >~moss Gary, I believe that you are incorrect. K&R (p146) states that: "Each conversion specification is introduced by the character % and ended by a conversion character. Between th % and the conversion character there may be: ... A length modifier l (letter ell), which indicates that the corresponding data item is a long rater than an int." The default type for printf is int. (We are talking about interger data types here: short, int and long.) Note that a short is promoted to an int by rule 6.1 in Appendix A (p183), which states that shorts and chars are promoted to ints in expressions. Therefor, the only integer type parameters are int and long. The %d conversion corresponds to int and the %ld corresponds to long. (The o, x, u and c conversion characters all expent an int. The e, f, and g conversion characters all expect a double, as floats are promoted to doubles by 6.2 (p184). o, x, and u just treat the int as unsigned. They are allowed to as signed and unsigned entities are the same length.) An interesting thing to note is that in the scanf family, the argument type must correspond EXACTLY to the conversion character. Thus, we have that d, o, and x expect an int; h expects a short; c expects a char; f expects a float; ld, lo, and lx expect a long; and lf expects a double. (Some of the above may have been changed in the ANSI standard. I don't have my copy of the draft here to look it up.) So we have that George was probably correct. (I didn't see his posting.) Incidentally, on a VAX, ints and longs are interchangeable. So the l spcifier is unnecessary for ints. (It is still necessary for doubles, though.) On my IBM-PC, C compilers use 16 bit ints, keeping with the rule that an int should be "the natural size for the machine, not smaller than a short, not larger than a long." So on my PC, I am more aware of int/long incompatibilities like this. -Israel ---------------------------------------------------------------------- Disclaimer: The above are my personal opinions, and in no way represent the opinions of Intel Corporation. In no way should the above be taken to be a statement of Intel. UUCP: {amdcad,decwrl,hplabs,oliveb,pur-ee,qantel}!intelca!mipos3!pinkas ARPA: pinkas%mipos3.intel.com@relay.cs.net CSNET: pinkas%mipos3.intel.com --------- "You can do more with a kind word and a gun than with just a kind word" -Al Capone
moss@BRL.ARPA (Gary S. Moss (SLCBR-VL-V)) (09/15/87)
Tim and Raymond, Thanks for the correction, you're absolutely right, INT is the natural size, LONG being longer on many machines, notably 16-bit ones (It's been a while since I used them). So, %ld is correct to use with PRINTF and LONGs. I must have been thinking of floats, but in any case, I guess I didn't think very much. Sorry for the mistake folks. ~moss
smvorkoetter@watmum.UUCP (09/16/87)
In article <9266@brl-adm.ARPA> moss@BRL.ARPA (Gary S. Moss (SLCBR-VL-V)) writes: > The format %ld is wrong when using the PRINTF family of functions. >The reason for this is that integer arguments are *always* widened to LONG From where did you get this piece of information? Char is always widened to int, and float to double, but never int to long. Stefan Vorkoetter University of Waterloo Symbolic Computation Group
steve@nuchat.UUCP (09/16/87)
In article <9266@brl-adm.ARPA>, moss@BRL.ARPA (Gary S. Moss) writes: > George, > The format %ld is wrong when using the PRINTF family of functions. > The reason for this is that integer arguments are *always* widened to LONG > when passed in to a function, so the %d format is meant for LONGS. This > is also true for %f. I am not certain, but pretty sure that I have gotten > wrong behavior when using %ld in this context on certain hardware. This can't be allowed to stand. In C, scalar types smaller than an int are promoted to _int_ when passed to a function, including printf. Thus there is no need for special provisions for printing shorts or chars as integers. But long may be larger than int, which you would know if you didn't program vax's or vax-alikes, and thus a special indicator is required for printing longs. > This is contrary to the SCANF family where you *need* the %ld because > you are placing the result in an address whose type is not known to the > function. True. One would also need special indicators for short and char if one wanted to be able to scanf '%d' into them. A similar thing happens with floting point: floats and doubles are passed to printf as double, so only one %f is needed. But scanf would have to know which was being pointed to to poke the converted value properly. -- Steve Nuchia Of course I'm respectable! I'm old! {soma,academ}!uhnix1 Politicians, ugly buildings, and whores !nuchat!steve all get respectable if they last long enough. (713) 334 6720 - John Huston, Chinatown
peter@sugar.UUCP (09/16/87)
In article <9266@brl-adm.ARPA>, moss@BRL.ARPA (Gary S. Moss (SLCBR-VL-V)) writes: > George, > The format %ld is wrong when using the PRINTF family of functions. Nope, it's right. > The reason for this is that integer arguments are *always* widened to LONG > when passed in to a function, so the %d format is meant for LONGS. Integer arguments are widened to INT when passed in to a function. If you always run on Vaxen and 68000s and the like (as you presumably have) you will never have any problems. If you run on PDP11s and 8086s you'll get the most amazing results. > This > is also true for %f. This is true for %f, but not for %d. Probably there didn't happen to be any performance advantage to using the longer floats on a PDP11 and this became entrenched in the language. > I am not certain, but pretty sure that I have gotten > wrong behavior when using %ld in this context on certain hardware. when either your compiler is wrong or you were really using an integer or (more likely) a pointer and assuming it was a long. Pointers may be longs on an 8086, but never are on a PDP11. The Vandata version of the Whitesmiths 'C' compiler on the 8080 actually promoted to char (i.e., didn't promote) when passing integers when you were compiling in the tightest possible mode. This was great for small embedded systems. -- -- Peter da Silva `-_-' ...!hoptoad!academ!uhnix1!sugar!peter -- 'U` ^^^^^^^^^^^^^^ Not seismo!soma (blush)
dave@westmark.UUCP (09/17/87)
In article <9266@brl-adm.ARPA>, moss@BRL.ARPA writes: > George, > The format %ld is wrong when using the PRINTF family of functions. > The reason for this is that integer arguments are *always* widened to LONG > when passed in to a function, so the %d format is meant for LONGS. This > is also true for %f. I am not certain, but pretty sure that I have gotten > wrong behavior when using %ld in this context on certain hardware. If this were true, why was %ld provided? I thought that chars and shorts got promoted to ints. Ints and longs happen to be the same size on some systems, but in general, ints get passed as ints. Printf expects an int when it sees %d and a long when it sees %ld. If they're the same size, you can use them interchangeably, unless you care about portability! -- Dave Levenson Westmark, Inc. A node for news. Warren, NJ USA {rutgers | clyde | mtune | ihnp4}!westmark!dave
gwyn@brl-smoke.ARPA (Doug Gwyn ) (09/21/87)
In article <9266@brl-adm.ARPA> moss@BRL.ARPA (Gary S. Moss (SLCBR-VL-V)) writes: >The reason for this is that integer arguments are *always* widened to LONG >when passed in to a function, so the %d format is meant for LONGS. This is completely wrong! Pre-ANSI C function arguments are widened, all right, but not to (long). All non-long integral types are widened to (int) (or (unsigned int), same size). %ld should not be used with (int) parameters to *printf(), but only with (long) parameters. Scanf(), since it takes pointers, is unaffected by parameter widening.