dave@westmark.UUCP (11/28/87)
Perhaps a C guru on the net can tell me what's wrong with this
trivial C program?
#include <stdio.h>
main()
{
long n;
n = (1 << 31) -1;
printf("%ld\n", n);
}
This is a simple example of a problem that affects a more complex
piece of someone's software that I'm trying to maintain.
If I compile this under UNIX, and run it, it prints 2147483647.
If I compile this under MS-DOS using Microsoft C Rel 3.0, and run
it, it gets the same answer!!! But if I compile it under MS-DOS
using Microsoft C Rel 4.0, it prints 65535. Has anyone tried
something like this under Microsoft C Rel 5.0?
Am I mis-using C? Is there a reason why the expression is
apparently evaluated as an int and then promoted to long in one
compiler but evaluated as a long in two others?
--
Dave Levenson
Westmark, Inc. A node for news.
Warren, NJ USA
{rutgers | clyde | mtune | ihnp4}!westmark!dave
gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/29/87)
In article <278@westmark.UUCP> dave@westmark.UUCP (Dave Levenson) writes: > long n; > n = (1 << 31) -1; Try changing the first "1" to "1L"; otherwise the whole expression is evaluated using (int)s, not (long)s, before the value is assigned. If (int) has 16 bits, the left-shift overflows and a variety of results are possible, including the one you reported. By the way, you're treading on thin ice anyway, since (1L << 31) is the most-negative 2's complement integer, so subtracting 1 from it is yet another undefined operation. I'm not sure what this code is trying to accomplish, but consider using unsigned long n; n = ((unsigned long)1 << 31) - 1;
platt@emory.uucp (Dan Platt) (11/29/87)
In article <278@westmark.UUCP> dave@westmark.UUCP (Dave Levenson) writes: >Perhaps a C guru on the net can tell me what's wrong with this >trivial C program? > >#include <stdio.h> >main() >{ > long n; > n = (1 << 31) -1; > printf("%ld\n", n); >} > > >Am I mis-using C? Is there a reason why the expression is >apparently evaluated as an int and then promoted to long in one >compiler but evaluated as a long in two others? I don't know if it's a mis-use. It would seem that there is some ambiguity over the issue if not all compilers treat this the same. It seems to me that most of the compilers that I've tried (on the Sun the DEC, and TurboC) treat this as the long answer. Yet I don't see any reason why it should. I would say that to make absolutely sure, you should code this as #include <stdio.h> main() { long n; n = (1L << 31) - 1; printf("%ld\n",n); } and see if this fixes the problem. If it doesn't then there's a bug in MSC4.0 (which they may or may not have fixed by 5.0). Dan Platt
ark@alice.UUCP (11/29/87)
In article <278@westmark.UUCP>, dave@westmark.UUCP writes: > Perhaps a C guru on the net can tell me what's wrong with this > trivial C program? > > #include <stdio.h> > main() > { > long n; > n = (1 << 31) -1; > printf("%ld\n", n); > } The value of the expression 1 << 31 is undefined on implementations where an int is less than 32 bits long. If you wish to evaluate 1<<31 as a long, you must write n = (1L << 31) -1; or some variation thereof.
ugfailau@sunybcs.uucp (Fai Lau) (11/29/87)
In article <6755@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <278@westmark.UUCP> dave@westmark.UUCP (Dave Levenson) writes: >> long n; >> n = (1 << 31) -1; > >Try changing the first "1" to "1L"; otherwise the whole expression >is evaluated using (int)s, not (long)s, before the value is assigned. >If (int) has 16 bits, the left-shift overflows and a variety of >results are possible, including the one you reported. > The left most bit of both long words of UNIX and Rel 3.0 are sign bits. The same is true for the integer of Rel 4.0. When you "overshift" a word or integer, the sign bit can only be shifted "on". That is, when the sign bit is turned on as a result of bit shifting, it can not be turned off again, unlike the other bits which represent the value of the number. So, when you over shift a word of any length, you'll always get a 1 on the left most bit, except in the case where the word itself is 0 (ie. has no "on" bit). In the above case, a 16 bit word is overshifted. What's left is a word with *only* the left most bit, the sign bit, turned on. This bit pattern represents an integer value of -65536 (I don't want to go into how the *value* of a negative number is represented). When you put - 1 on it, overthrow occurs, as the number -65536 is the smallest integer a 16 bit word can represent. Therefore, instead of -65537, you get a positive integer of 65535, with every bit of the word turned on except the sign bit. Incidently, this value is the maximum that can be stored in the 16 bit word. Notice that every value bit is used up. This value is then stored in the long word n. That is why you got the value you did when you print n. As a matter of fact, the supposedly correct value you get from UNIX and Rel 3.0 is a result from negative overflowing too. This value is the maximum positive number that can be stored in the 32 bit long words of UNIX and Rel 3.0. >By the way, you're treading on thin ice anyway, since (1L << 31) is >the most-negative 2's complement integer, so subtracting 1 from it >is yet another undefined operation. I'm not sure what this code is >trying to accomplish, but consider using > unsigned long n; > n = ((unsigned long)1 << 31) - 1; The operation is not undefine. By observing the result, we can 1) identify the scheme with which the system store negative numbers, 2) what length of word is used as default for operation like <<. Using much larger number in place of 31 doesn't hurt. (not original intent, of course) Fai Lau SUNY at Buffalo (The Arctic Wonderland) UUCP: ..{mit-ems|watmath|rocksanne}!sunybcs!ugfailau BI: ugfailau@sunybcs
chris@mimsy.UUCP (Chris Torek) (11/29/87)
In article <278@westmark.UUCP> dave@westmark.UUCP (Dave Levenson) writes: >#include <stdio.h> >main() >{ > long n; > n = (1 << 31) -1; > printf("%ld\n", n); >} > >If I compile this under UNIX, and run it, it prints 2147483647. (You do not say on which machine---probably one with 32 bit ints.) >If I compile this under MS-DOS using Microsoft C Rel 3.0, and run >it, it gets the same answer!!! But if I compile it under MS-DOS >using Microsoft C Rel 4.0, it prints 65535. That is a bit peculiar. I would expect 1<<31 to be (int)0, then (int)0-(int)1 to be (int)-1, which should produce (long)-1 when extended. >Am I mis-using C? Yes: use (1L << 31) - 1, or (1 << 31L) - 1, or ((long)1 << 31) - 1, or . . . . If you shift something too many positions, I believe the result is officially undefined; this gives MS C license to come up with anything, including the rather ludicrous 65535, or the more reasonable -1, or even 2147483647. (I would be more certain but my references are at work and I am not.) At a guess, I would say that MS C 3.0 noticed the shift count of 31 and put in the (long)s for you, and that this feature(?) was removed from release 4.0. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
chris@mimsy.UUCP (Chris Torek) (11/29/87)
In article <6855@sunybcs.UUCP> ugfailau@sunybcs.uucp (Fai Lau) writes: > The left most bit of both long words of UNIX and Rel 3.0 >are sign bits. The same is true for the integer of Rel 4.0. >When you "overshift" a word or integer, the sign bit can only >be shifted "on". That is, when the sign bit is turned on as >a result of bit shifting, it can not be turned off again, .... This may be true for left shifts, although I doubt it. It is probably true for right shifts. > In the [original example], a 16 bit word is overshifted. >What's left is a word with *only* the left most bit, the sign >bit, turned on. This bit pattern represents an integer >value of -65536 (I don't want to go into how the *value* >of a negative number is represented). Nonsense. The pattern 0x8000 as a signed two's complement 16 bit value represents -32768. >>By the way, you're treading on thin ice anyway, since (1L << 31) is >>the most-negative 2's complement integer, so subtracting 1 from it >>is yet another undefined operation. [Doug Gwyn] > The operation is not undefine. Again, nonsense. The result is undefined *in C*. No doubt the operation on any given system is predictable (though possibly with difficulty: a compiler is free to implement underflow by replacing the value with the time of day, or the apparent diameter of the lit region of the moon, or soemthing equally absurd). Most will ignore the underflow and change 0x80000000 to 0x7fffffff; others may trap and give you a core dump. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/30/87)
In article <6855@sunybcs.UUCP> ugfailau@joey.UUCP (Fai Lau) writes: >In article <6755@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >That is, when the sign bit is turned on as >a result of bit shifting, it can not be turned off again, Is this REALLY true of the 80*86 family? If so, it's the only architecture I've ever heard of that behaves this way. > The operation is not undefine. By "undefined" I meant, undefined by the C language specification. Obviously the hardware will do SOMEthing.
jru@etn-rad.UUCP (John Unekis) (12/01/87)
In article <6761@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <6855@sunybcs.UUCP> ugfailau@joey.UUCP (Fai Lau) writes: >>In article <6755@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >>That is, when the sign bit is turned on as >>a result of bit shifting, it can not be turned off again,...... >Is this REALLY true of the 80*86 family? If so, it's the only >architecture I've ever heard of that behaves this way...... No, It is not true. I think Doug was confused by the difference between a logical shift instruction, and an arithmetic shift. With either type of shift, a left shift places the next-to-most-significant bit into the most-signifacant-bit , whether it is a one or a zero. When you perform a right shift however, the logical shift moves everything down one bit and turns off(makes zero) the high bit. The arithmetic shift moves everything down one bit and leaves the high bit set to its previous value(whether one or zero). Since the high bit is the sign bit, this leaves a negative number negative after the shift. Microsoft C uses the arithmetic shift whenever you do a >> shift in C. This is nice in a way, because a right shift by one bit is always equal to a divide by two. That is 4 >> 1 = 2, and -4 >> 1 = -2. It does however lead to some frustration if you are using shift operations to isolate something like bit flags. If you take a 16bit integer and put the value 32767 in it, you get 0111111111111111 in binary, a left shift gives you 1111111111111110, which is a -2, If you follow with a right shift, you get 1111111111111111, which is a -1. So a right shift is not always the inverse of a left shift in Microsoft C. If it is important to you not to propagate the sign bit , I suggest you follow a right shift with an and operation such as result = (value >> n) & (32767 >> (n-1)). It is a horrible kludge, but it may be easier than coding an assembler routine to perform a logical right shift instead of the arithmetic right shift. I am not particularly fond of intel 80?86 hardware, but they are not THAT bad.
gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/01/87)
In article <312@etn-rad.UUCP> jru@etn-rad.UUCP (John Unekis) writes: -In article <6761@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: ->In article <6855@sunybcs.UUCP> ugfailau@joey.UUCP (Fai Lau) writes: ->>In article <6755@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: ->>That is, when the sign bit is turned on as ->>a result of bit shifting, it can not be turned off again,...... ->Is this REALLY true of the 80*86 family? If so, it's the only ->architecture I've ever heard of that behaves this way...... -No, It is not true. I think Doug was confused by the difference between a -logical shift instruction, and an arithmetic shift. ... I'm afraid I confused you by including one too many "... writes:" lines. I (Doug) am well aware of the differences between types of shifts. However, Fai Lau posted a fascinating "correction" to my correct response, claiming a new and unusual form of brain damage, presumably for the 80*86 architecture (since these messages have been cross-posted to comp.sys.ibm.pc). -I am not particularly fond of intel 80?86 hardware, but they are not -THAT bad. I didn't think it could really be..
tim@amdcad.AMD.COM (Tim Olson) (12/01/87)
In article <312@etn-rad.UUCP> jru@etn-rad.UUCP (John Unekis) writes: | ... Microsoft C uses the arithmetic shift whenever | you do a >> shift in C. This is nice in a way, because a right shift by | one bit is always equal to a divide by two. That is 4 >> 1 = 2, and | -4 >> 1 = -2. This is not true. First of all, right shift is not guaranteed to be arithmetic for signed integers. Second, most computers and languages define integer divide to round towards zero, not negative infinity. Therefore, substituting >> for a division by a power of 2 is not correct (unless you also include the fixup code for odd negative dividends). | If it is important | to you not to propagate the sign bit , I suggest you follow a right shift | with an and operation such as result = (value >> n) & (32767 >> (n-1)). It | is a horrible kludge, but it may be easier than coding an assembler routine | to perform a logical right shift instead of the arithmetic right shift. Why not just use unsigned operands? Right shift is required to be logical (zero-fill) for unsigned ints. -- Tim Olson Advanced Micro Devices (tim@amdcad.amd.com)
ugfailau@sunybcs.uucp (Fai Lau) (12/02/87)
In article <9562@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >In article <6855@sunybcs.UUCP> ugfailau@sunybcs.uucp (Fai Lau) writes: >> ..... >>be shifted "on". That is, when the sign bit is turned on as >>a result of bit shifting, it can not be turned off again, .... > >This may be true for left shifts, although I doubt it. It is >probably true for right shifts. > It *is* true for every version of C I've ever worked on. I don't know about the machines. I made a mistake by not mentioning the shift is "left" shift. I am not sure know about right shift. The result puzzles me too. I remember I've worked on bit shifts on C before, it took me a lot of agony to realize this characteristic. >> In the [original example], a 16 bit word is overshifted. >>What's left is a word with *only* the left most bit, the sign >>bit, turned on. This bit pattern represents an integer >>value of -65536 (I don't want to go into how the *value* >>of a negative number is represented). > >Nonsense. The pattern 0x8000 as a signed two's complement 16 >bit value represents -32768. > True. I forgot the positive half. 16 bits can only represent 65536 integers. With 32767 positive integers and one 0, there are only 32768 negative integers. But the misinterpretation of the 16th bit still holds true. > >> The operation is not undefine. > >Again, nonsense. The result is undefined *in C*. No doubt the >operation on any given system is predictable (though possibly with >difficulty: a compiler is free to implement underflow by replacing >the value with the time of day, or the apparent diameter of the >lit region of the moon, or soemthing equally absurd). Most will >ignore the underflow and change 0x80000000 to 0x7fffffff; others >may trap and give you a core dump. >-- It is all in how you see it. If you know the behavior of your machine, you can no doubt use the over flow characteristic as a defined function. A function which returns an undefined result in certain input circumstances can be considered defined in all input circumstanc if the undefined output is predictable and is indeed included in the set of output which is considered, $$$filler $$$filler is a necessary evil $$$filler $$$filler ???Enough??? Fai Lau SUNY at Buffalo (The Arctic Wonderland) UUCP: ..{mit-ems|watmath|rocksanne}!sunybcs!ugfailau BI: ugfailau@sunybcs
ugfailau@sunybcs.uucp (Fai Lau) (12/02/87)
In article <6761@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <6855@sunybcs.UUCP> ugfailau@joey.UUCP (Fai Lau) writes: >>In article <6755@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >>That is, when the sign bit is turned on as >>a result of bit shifting, it can not be turned off again, > >Is this REALLY true of the 80*86 family? If so, it's the only >architecture I've ever heard of that behaves this way. Oops. I should have emphasized that it *can* be turned off!! But using other ways except left shift (logical bits operations come to mind). Fai Lau SUNY at Buffalo (The Arctic Wonderland) UUCP: ..{mit-ems|watmath|rocksanne}!sunybcs!ugfailau BI: ugfailau@sunybcs
ugfailau@sunybcs.uucp (Fai Lau) (12/02/87)
In article <6767@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <312@etn-rad.UUCP> jru@etn-rad.UUCP (John Unekis) writes: >-In article <6761@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >->In article <6855@sunybcs.UUCP> ugfailau@joey.UUCP (Fai Lau) writes: >->>In article <6755@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >->>That is, when the sign bit is turned on as >->>a result of bit shifting, it can not be turned off again,...... >->Is this REALLY true of the 80*86 family? If so, it's the only >->architecture I've ever heard of that behaves this way...... >-No, It is not true. I think Doug was confused by the difference between a >-logical shift instruction, and an arithmetic shift. ... > >I'm afraid I confused you by including one too many "... writes:" lines. >I (Doug) am well aware of the differences between types of shifts. >However, Fai Lau posted a fascinating "correction" to my correct response, >claiming a new and unusual form of brain damage, presumably for the 80*86 >architecture (since these messages have been cross-posted to comp.sys.ibm.pc). > It's a no-no, Doug. For a while I thought you had to be one of those mischievious little brats that whouldn't listen but keep insisting on fooling around with their old man's PC. But then I had my doubt. You know how to spell "brain damage". Nevertheless It is quite amusing to observe the hilarity of your attempt at commanding the written language. Despicable manners aside, your inability of organizing ideas in words can only be matched by your ignorance of facts so prominently displayed in your paltry writing. As those of us who have noticed that particular article I posted have already know, the only thing that I even came close to "correcting" you was on the issue of whether overshifting in C is defined. I had my opinion. And I was speaking more from a system point of view. I wasn't interested in the science of the programming language. But of course this whole thing I wrote left your miniscule mind utterly perplexed and hopelessly confused. But then I had no intention of lowering myself to speak at your level. Well, folks, I better stop before it gets out of hand. I understand that this kind of bantering is very inappropriate for this news group, but someone's got to do the dirty job of putting Doug in his place, before he again posts anything offensive and mindless they way he did. Remember, Doug, a man is never too old to learn, or too young to get spanked! ;-):-);-):-);-P:-|;-P:-| Fai Lau SUNY at Buffalo (The Arctic Wonderland) UUCP: ..{mit-ems|watmath|rocksanne}!sunybcs!ugfailau BI: ugfailau@sunybcs
gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/02/87)
In article <6949@sunybcs.UUCP> ugfailau@joey.UUCP (Fai Lau) writes: >Remember, Doug, a man is never too old to learn, or too young to get spanked! I don't know who this turkey thinks he is, but regular readers of the C newsgroup undoubtedly are in a position to make up their own minds about the reliability of the various contributors to the recent discussion about the behavior of shift operators (which really had little to do with the original question!).
mcdonald@uxe.cso.uiuc.edu (12/02/87)
/* Written 6:37 pm Nov 30, 1987 by jru@etn-rad.UUCP in uxe.cso.uiuc.edu:comp.lang.c */
negative after the shift. Microsoft C uses the arithmetic shift whenever
you do a >> shift in C. This is nice in a way, because a right shift by
/* End of text from uxe.cso.uiuc.edu:comp.lang.c */
Only on signed quantities. Consider this C subroutine and the compiler output
(dead code deleted):
a(b,c)
int b;
unsigned c;
{
b >>= 1;
c >>= 1;
}
_a PROC NEAR
push bp
mov bp,sp
sar WORD PTR [bp+4],1 ;b sar is arithmetic
shr WORD PTR [bp+6],1 ;c shr is logical
mov sp,bp
pop bp
ret
a ENDP
Doug McDonald
sdutcher@netxcom.UUCP (Sylvia Dutcher) (12/03/87)
I have checked a couple pf references and have found the following defenitions. ARITHMETIC SHIFT - An arithmetic shift is a microoperation that shifts a *signed* binary number to the left or right. An arithmetic shift-left multiplies a signed binary number by 2. An arithmetic shift-right divides the number by 2. Arithmetic shifts must leave the sign of the number unchanged because the sign of the number remains the same when it is multiplied or divided by 2. (Mano, Digital Logic and Computer Design, p329) LOGICAL SHIFT - A shift operation with 0 inserted in the extreme bit is considered a logical shift microoperation. (Ibid, p339) Just to confuse things, Kernighan & Ritchie say (p45) " ... x << 2 shifts x left by two positions, filling vacated bits with 0; this is equivalent to multiplication by 4. Right shifting an *unsigned* quantity fills vacated bits with 0. Right shifting a signed quantity will fill with sign bits ("arithmetic shift") on some machines .....and with 0-bits ("logical shift") on others. So I guess you're all right! -- Sylvia Dutcher NetExpress Communications, Inc. 1953 Gallows Rd. Vienna, Va. 22180
john@frog.UUCP (John Woods, Software) (12/03/87)
In article <6949@sunybcs.UUCP>, ugfailau@sunybcs.uucp (Fai Lau) writes: >[A maze of twisty little 'In article <foo>, {baz} writes:' deleted] > >I (Doug) am well aware of the differences between types of shifts. > >However, Fai Lau posted a fascinating "correction" to my correct response, > > It's a no-no, Doug. For a while I thought you had to be one > of those mischievious little brats that whouldn't listen but keep > insisting on fooling around with their old man's PC. But then I > had my doubt. You know how to spell "brain damage". > Nevertheless It is quite amusing to observe the hilarity > of your attempt at commanding the written language. Despicable > manners aside, your inability of organizing ideas in words can > only be matched by your ignorance of facts so prominently displayed > in your paltry writing. I find this truly amazing. One of the most professional fonts of wisdom on comp.lang.c (namely Doug) is being flamed by some idiot who clearly doesn't understand anything more complicated than how to boot his PC. > issue of whether overshifting in C is defined. I had my > opinion. And I was speaking more from a system point of > view. I wasn't interested in the science of the programming > language. In short, it IS NOT defined, your opinion is worthless, and evidently you weren't interested in understanding what you were talking about, either. (What "system point of view"?) Try shutting up until you do. >Remember, Doug, a man is never too old to learn, or too young to get spanked! > Fai Lau Wise words. Remember them yourself, or get ready to be spanked by everyone on USENET who knows what they're talking about. That's fewer than it should be, but more than you would want. -- John Woods, Charles River Data Systems, Framingham MA, (617) 626-1101 ...!decvax!frog!john, ...!mit-eddie!jfw, jfw@eddie.mit.edu "Cutting the space budget really restores my faith in humanity. It eliminates dreams, goals, and ideals and lets us get straight to the business of hate, debauchery, and self-annihilation." -- Johnny Hart
lmiller@venera.isi.edu (Larry Miller) (12/03/87)
In article <6949@sunybcs.UUCP> ugfailau@joey.UUCP (Fai Lau) writes: > Well, folks, I better stop before it gets out of hand. >I understand that this kind of bantering is very inappropriate >for this news group, but someone's got to do the dirty >job of putting Doug in his place, before he again posts anything >offensive and mindless they way he did. Remember, Doug, >a man is never too old to learn, or too young to get >spanked! ;-):-);-):-);-P:-|;-P:-| > >Fai Lau >SUNY at Buffalo (The Arctic Wonderland) >UUCP: ..{mit-ems|watmath|rocksanne}!sunybcs!ugfailau >BI: ugfailau@sunybcs As a regular reader of this news group, and as someone who as written or co-written several programming language texts, I think Doug's contributions to this group have been accurate, timely, and a boon to all C programmers. The time and effort he puts in to contributions to this group are enormous, and frankly, beyond what one would hope for. It would be a shame if he were to decide not to involve himself because of this thoughtless, ugly, posting my Mr. Lau. Larry Miller lmiller@venera.isi.edu (no uucp) USC/ISI 213-822-1511 4676 Admiralty Way Marina del Rey, CA. 90292
jru@etn-rad.UUCP (John Unekis) (12/03/87)
In article <19390@amdcad.AMD.COM> tim@amdcad.UUCP (Tim Olson) writes: >In article <312@etn-rad.UUCP> jru@etn-rad.UUCP (John Unekis) writes: >| ... Microsoft C uses the arithmetic shift whenever > >This is not true. First of all, right shift is not guaranteed to be >arithmetic for signed integers. Second, most computers and languages ..... The discussion was not of MOST computers, it was regarding the Intel 80?86, and I specifically referenced Microsoft C, which does use the arithmetic shift for right shifting integers.
brianc@cognos.uucp (Brian Campbell) (12/03/87)
In article <6755@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: ! In article <278@westmark.UUCP> dave@westmark.UUCP (Dave Levenson) writes: ! > long n; ! > n = (1 << 31) -1; ! ! Try changing the first "1" to "1L"; otherwise the whole expression ! is evaluated using (int)s, not (long)s, before the value is assigned. ! If (int) has 16 bits, the left-shift overflows and a variety of ! results are possible, including the one you reported. ! ! By the way, you're treading on thin ice anyway, since (1L << 31) is ! the most-negative 2's complement integer, so subtracting 1 from it ! is yet another undefined operation. I'm not sure what this code is ! trying to accomplish, but consider using ! unsigned long n; ! n = ((unsigned long)1 << 31) - 1; I don't think this is good advice. Unless the assigment is supposed to be setting all bits except the 32nd, I think Dave should be assigning from a define. The LONG_MAX defined in <limits.h> sounds ideal, although its defined in <values.h> and is called MAXLONG on my machine ... -- Brian Campbell uucp: decvax!utzoo!dciem!nrcaer!cognos!brianc Cognos Incorporated mail: POB 9707, 3755 Riverside Drive, Ottawa, K1G 3Z4 (613) 738-1440 fido: (613) 731-2945 300/1200, sysop@1:163/8
chris@mimsy.UUCP (12/04/87)
In article <314@etn-rad.UUCP> jru@etn-rad.UUCP (John Unekis) writes: >The discussion was not of MOST computers, it was regarding the Intel >80?86, and I specifically referenced Microsoft C, which does use the >arithmetic shift for right shifting integers. The discussion was neither `of most computers' nor `regarding the Intel 80?86': the discussion started with a question about the language C, in which the type of right shift for signed integers is left unspecified (at least in K&R). It was placed in a context which referenced Microsoft C, but the question itself was more generic. Never assume that mere mention of one particular means that those reading your article will view it as being restricted to that particular. To John Woods, who flamed Fai Lau for flaming Doug Gwyn: Please do not be *too* harsh. Fai Lau's point (which I regard as being `by observing the results of various technically-undefined operations, one can determine, to some extent, the inner workings of one's system') is valid. It is unfortunate that he had obscured that point with incorrect `facts' and confusing wording. I seem to be good at left-handed compliments! Perhaps it is because I am left handed. :-) At any rate, can we stop this discussion, now that we have settled upon the following: In C as it is currently defined (K&R), - the result of left shifting an `int' value by 31 bits is undefined - the result of subtracting 1 from the most negative `int' value a system can represent is undefined - whether right shift is arithmetic or logical is undefined In MS C for the IBM PC, - the `most negative' `int' value is -32768 - right shift of a signed integer quantity is done with an arithmetic (sign-preserving) shift - right shift of an unsigned integer quantity is done with a logical (zero-filling) shift -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
ugfailau@sunybcs.UUCP (12/04/87)
It is getting ridiculous. I will make my absolute last post regarding this incident. I apologize for my last outburst. As I said it was very inappropriate to post flame the way I did in this news group, especially in such bad faith. This is, after all, not the Insult Board of my school, which I once took much pleasures in and from which I have retired. I was very angry with Doug's name-calling post so I though that that would be a pretty good excuse to try my skill, or whatever's left of it. Again, I think my post was excessive. So in order to be fair, I'll swallow John Woods' more juvenile portion of his post without any rebuttal. And I don't want to see another thing regarding this incident again. I wish I could move this article to soc.insult and truly indulge myself at John Woods' expense, but then such news group doesn't exist. So I'll have to settle, and so will everybody. In article <1958@frog.UUCP> john@frog.UUCP (John Woods, Software) writes: > >I find this truly amazing. One of the most professional fonts of wisdom >on comp.lang.c (namely Doug) is being flamed by some idiot who clearly doesn't >understand anything more complicated than how to boot his PC. > >In short, it IS NOT defined, your opinion is worthless, and evidently >you weren't interested in understanding what you were talking about, >either. (What "system point of view"?) Try shutting up until you do. > System point of view means to consider the behavior of a software (or particular, a language) as a subset of the system. There are many definitions regarding how many softwares ought to behavior in an ideal environment, on paper, in theory, according to formulas. But in the real world we have to implement such ideals in an un-ideal machines, and used by 'imperfect' humans. As a result there are things ending up being different from the deffinitions and the theories. For example, Lisp. The concept of Lisp looks like it's the best thing ever happened to AI research (at least when it first came out), and we certainly admired its potentials at one time. Lisp is widely used today. And you know what happens? It's just another programming language. We recurse like a bat out of hell, and then find out what a pain on the butt it could be keeping track of those lists within lists. And we start using setqs, iteration whenever it's more convenient. Just how much spirit is left? Are the original wine and roses evident in our codes? Another example. When Modula-1 first came out, it was supposed to be a very structured language which would replace Pascal, and which would provide good low level access. It incorporated data abstraction, the idea of modules, better scope and extend controls, etc.. and the result should be something less error prone and more complete. But so what? Have Do you seen Turbo Modula-2? I've tried Modula-2 on mainframe. What looks good on paper doesn't necessary work well in the real world. So what am I getting at? Strict language definition looks good in a text book. And it would be nice to be followed precisely in the developing of theories. But in the real world you cannot separate the language from the machine it is being implemented in. Granted portability may suffer if a programmer went beyond what's in the book in his command of a language, but if the circumstances allow it should not be forbidden, or even discouraged. And of course it is frequently done. Personally I don't like doing things by the books. And I believe certain definitions of a language is most useful when it is defined under the circumstances where *you* use it. >Wise words. Remember them yourself, or get ready to be spanked by everyone >on USENET who knows what they're talking about. That's fewer than it should >be, but more than you would want. > See I swallowed it! Fai Lau SUNY at Buffalo (The Arctic Wonderland) UUCP: ..{mit-ems|watmath|rocksanne}!sunybcs!ugfailau BI: ugfailau@sunybcs
gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/04/87)
In article <6996@sunybcs.UUCP> ugfailau@joey.UUCP (Fai Lau) writes: >I was very angry with Doug's name-calling post... Perhaps you should try harder to understand things before reacting to them. If it was the epithet "brain-damaged" that you objected to, be advised that it was directed at the architecture you described (where sign bits stuck in the "on" state on a left shift). This is standard terminology for architectural design defects. A later poster has advised that the 80*86 architecture does not behave the way you described it. You can find out by running the following test on your toy computer; I don't have convenient access to one or I would have tried it myself: #include <stdio.h> main() { register short i; /* make sure it's 16 bits */ register int j; for (i = 0x5555, j = 0; j < 16; ++j) { i <<= 1; if (j % 2 && i & 0x8000) { printf("Fai Lau was right!\n"); return 0; } } printf("Gobble, gobble!\n"); return 1; } >Personally I don't like doing things by the books. The approach you said you take to the use of programming languages will get you into great trouble when you have to port megalines of source code to dozens of disparate environments. Those of us who have done this over the past couple of decades have learned how to avoid, or at least harness, machine dependencies in our code. We most certainly DO discourage exploiting machine dependencies under most circumstances, and C signed right-shift sign propagation (or lack of it) is one of the things you should avoid relying on. Try taking advantage of other people's experience so you don't have to learn everything the hard way.