473,587 Members | 2,527 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

"Interestin g" C behaviours

In the last few days, I have discovered two "interestin g" behaviours of
the C language, both of which are apparently correct. Could someone
please explain the reasoning behind them?

1. The operators '^', '&', and '|' have lower precedance than '==',
'!=', '>=", etc. I discovered this when the statement "if (array1[i] ^
array2[i] == 0xff)" failed to do what I expected. To me, it doesn't
make any sense to give the bitwise operators lower precedance than
comparators. I can't see any situation where someone would want to
perform a bitwise operation on a truth value, but that is what the
language specifies for the above expression.

2. In C99, the expression 'a%b' where a<0 and b>0 will return a negative
result (K&R lets this be machine dependent). While it is technically
correct (-1 is congruent to 6 mod 7), it isn't exactly what most people
expect. Mathematically, the congruence classes modulo n are usually
expressed as [0], [1], ... [n-1]. The value -1 would be a member of the
congruence class [n-1]. So, when I'm performing certain operations, I
have to check if a number is negative, and if so, add the modulus to the
residue to get a sensible result. (For example, when subtracting two
struct timevals, and passing the result to select(). select() will barf
if the tv_usec field is negative, at least on Linux, so I have to set it
to (a.tv_usec-b.tv_usec)%1000 000, and then add 1000000 if the result is
negative.)

Rennie
Nov 14 '05 #1
6 1648

"Rennie deGraaf" <ca.ucalgary.cp sc@degraaf> wrote
In the last few days, I have discovered two "interestin g" behaviours of
the C language, both of which are apparently correct. Could someone
please explain the reasoning behind them?

1. The operators '^', '&', and '|' have lower precedance than '==',
'!=', '>=", etc.
You'd have to ask K and R about this. The problem is that the language was
designed by two people in a back room somewhere, and once set, the
precedence rules are very difficult to change.
2. In C99, the expression 'a%b' where a<0 and b>0 will return a negative
result (K&R lets this be machine dependent).

That would probably be driven by architecture. The idea is that a % b would
compile to a single machine instruction (on K and R's original platform).
Just a guess, but I suspect this is the motivation.
Nov 14 '05 #2
In article <sBUpd.360758$% k.84068@pd7tw2n o>
Rennie deGraaf <ca.ucalgary.cp sc@degraaf> wrote:
In the last few days, I have discovered two "interestin g" behaviours of
the C language, both of which are apparently correct. Could someone
please explain the reasoning behind them?

1. The operators '^', '&', and '|' have lower precedance than '==',
'!=', '>=", etc. I discovered this when the statement "if (array1[i] ^
array2[i] == 0xff)" failed to do what I expected. To me, it doesn't
make any sense to give the bitwise operators lower precedance than
comparators. I can't see any situation where someone would want to
perform a bitwise operation on a truth value, but that is what the
language specifies for the above expression.
Dennis Ritchie has noted that, in Primeval C, there were no "&&" and
"||" operators at all, and the single "&" and single "|" operators
were overloaded, so that:

result = f() | g();

would call both f() and g(), and bitwise-OR the results together to
store in the variable "result", while:

if (f() | g())

would call f() first, and if the result was nonzero, would omit the
call to g() entirely (i.e., what || does now). Likewise:

result = f() & g();

always called both, while:

if (f() & g())

called g() only if f() returned a nonzero value. Stopping as soon
as the result is known is called "short-circuit behavior". Presumably
the operators' priorities were set based on the short-circuit
versions, which probably occurred more often.

At some point, it was deemed bogus to have a single operator for
two entirely separate meanings, so the short-circuit logical
operators were separated out into new && and || operators. But by
then there were perhaps a few dozens of kilobytes :-) of source
code, so the operator parsing was left unchanged.
2. In C99, the expression 'a%b' where a<0 and b>0 will return a negative
result (K&R lets this be machine dependent). While it is technically
correct (-1 is congruent to 6 mod 7), it isn't exactly what most people
expect.
I think you have overly high expectations of "most people" here. :-)
Mathematically , the congruence classes modulo n are usually
expressed as [0], [1], ... [n-1].


True; but the "%" operator is really the "remainder after division"
operator. The goal is to have (a/b + a%b) == a, whenever b != 0.
To have ((-3) % 7) == 4, we would have to have ((-3) / 7) == -1),
but 0 is the most common result today for this division. Thus,
machines with "remainder after divide" instructions mostly produce
-3 here, and machines without such an instruction require computing
(a % b) via (a - (a / b) * b) in the first place.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #3
Malcolm wrote:
"Rennie deGraaf" <ca.ucalgary.cp sc@degraaf> wrote

2. In C99, the expression 'a%b' where a<0 and b>0 will return a negative
result (K&R lets this be machine dependent).


That would probably be driven by architecture. The idea is that a % b would
compile to a single machine instruction (on K and R's original platform).
Just a guess, but I suspect this is the motivation.


It was architecture dependent in K&R, but C99 standardized it (see
http://home.tiscalinet.ch/t_wolf/tw/...html#Semantics,
section 25). I know that the x86 idiv instruction spits out negative
residues, but is the fact that a common architecture does something
unusual a reason to standardize a programming language on an unusual
behaviour? It would make more sense to me to work around the
architecture when it does something weird.

GCC, for instance, frequently doesn't even compile a%b to a single idiv
instruction - it compiles it to a big mess of imul, shift, and leal
instructions.

Rennie
Nov 14 '05 #4
Rennie deGraaf <ca.ucalgary.cp sc@degraaf> wrote:
In the last few days, I have discovered two "interestin g" behaviours of
the C language, both of which are apparently correct. Could someone
please explain the reasoning behind them?

1. The operators '^', '&', and '|' have lower precedance than '==',
'!=', '>=", etc. I discovered this when the statement "if (array1[i] ^
array2[i] == 0xff)" failed to do what I expected. To me, it doesn't
make any sense to give the bitwise operators lower precedance than
comparators. I can't see any situation where someone would want to
perform a bitwise operation on a truth value, but that is what the
language specifies for the above expression.
I believe it is mostly historical baggage from the earliest C
compilers.


2. In C99, the expression 'a%b' where a<0 and b>0 will return a negative
result (K&R lets this be machine dependent). While it is technically
correct (-1 is congruent to 6 mod 7), it isn't exactly what most people
expect. Mathematically, the congruence classes modulo n are usually
expressed as [0], [1], ... [n-1]. The value -1 would be a member of the
congruence class [n-1]. So, when I'm performing certain operations, I
have to check if a number is negative, and if so, add the modulus to the
residue to get a sensible result. (For example, when subtracting two
struct timevals, and passing the result to select(). select() will barf
if the tv_usec field is negative, at least on Linux, so I have to set it
to (a.tv_usec-b.tv_usec)%1000 000, and then add 1000000 if the result is
negative.)


It should always be true that (a/b)*b+(a%b) == a, if b is non-zero.
When you have negative values involved the behaviour of the '%'
operator therefore depends on the behaviour of the '/' operator.
In C89 it was implementation-dependent which way '/' truncated when it
had negative operands. In C99 this was fixed as being towards zero.
I believe this change was made for compatibility with Fortran (which
has always done it the same way as C99 does.)
--
<Insert your favourite quote here.>
Erik Trulsson
er******@studen t.uu.se
Nov 14 '05 #5
In article <lJVpd.356735$n l.170987@pd7tw3 no>,
Rennie deGraaf <ca.ucalgary.cp sc@degraaf> wrote:
GCC, for instance, frequently doesn't even compile a%b to a single idiv
instruction - it compiles it to a big mess of imul, shift, and leal
instructions.


Because it is faster.
Nov 14 '05 #6
Erik Trulsson wrote:
Rennie deGraaf <ca.ucalgary.cp sc@degraaf> wrote:
(snip)
2. In C99, the expression 'a%b' where a<0 and b>0 will return a negative
result (K&R lets this be machine dependent). While it is technically
correct (-1 is congruent to 6 mod 7), it isn't exactly what most people
expect.
It is what most hardware designers expect.
So, when I'm performing certain operations, I
have to check if a number is negative, and if so, add the modulus to the
residue to get a sensible result.


I do it by adding the modulus and an additional %,

a=(x%y+y)%y;

It is unknown if the branch penalty is more or less than the
cost of the extra divide. It is less typing, anyway.
It should always be true that (a/b)*b+(a%b) == a, if b is non-zero.
When you have negative values involved the behaviour of the '%'
operator therefore depends on the behaviour of the '/' operator.
In C89 it was implementation-dependent which way '/' truncated when it
had negative operands. In C99 this was fixed as being towards zero.
I believe this change was made for compatibility with Fortran (which
has always done it the same way as C99 does.)


Well, there is a chicken and egg problem. Pretty much all
twos complement machines do it that way. I am not sure at
all what ones complement machines do. It might be, though,
that machines do it that way because Fortran does it that
way. From the Fortran 66 standard:

"The function MOD or AMOD(a1,a2) is defined as a1-[a1/a2]*a2
where [x] is the integer whose magnitude does not exceed
the magnitude of x, and whose sign is the same as x."

Note that many early Fortran machines were sign magnitude
or ones complement machines, and that C89 supports both
sign magnitude and ones complement arithmetic.
(I am not sure about C99.)

-- glen

Nov 14 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
2118
by: Jordan Rastrick | last post by:
First, a disclaimer. I am a second year Maths and Computer Science undergraduate, and this is my first time ever on Usenet (I guess I'm part of the http generation). On top of that, I have been using Python for a grand total of about a fortnight now. Hence, I apologise if what follows is a stupid suggestion, or if its already been made...
3
3240
by: eiselekd | last post by:
Does anyone know about a code snippet that can be used to output a backtrace just like gdb's "backtrace" command does. One that can be called on a segmentation fault. (without resolving symbol names, just simple list of frames until the main() stack frame)
72
4168
by: Paminu | last post by:
In math this expression: (a < b) && (b < c) would be described as: a < b < c But why is it that in C these two expressions evaluate to something different for the same values of a, b and c?
2
720
by: Zygo Blaxell | last post by:
I have a table with a few million rows of temperature data keyed by timestamp. I want to group these rows by timestamp intervals (e.g. every 32 seconds), compute aggregate functions on the columns, and ultimately feed the result into a graph-drawing web thingy. I'm trying a few different ways to get what seems to be the same data, and seeing...
43
2702
by: markryde | last post by:
Hello, I saw in some open source projects a use of "!!" in "C" code; for example: in some header file #define event_pending(v) \ (!!(v)->vcpu_info->evtchn_upcall_pending & \ !(v)->vcpu_info->evtchn_upcall_mask) whereas evtchn_upcall_pending is of type unsigned char (and also evtchn_upcall_mask is of type unsigned char).
60
5015
by: Dave | last post by:
I'm never quite sure whether to use "this." or not when referring to fields or properties in the same class. It obviously works just fine without it but sometimes I wonder if using this. consistently may make the code easier to understand for someone else, etc. Using "this." makes it immediately clear, for example, that the variable being...
11
1579
by: John Coleman | last post by:
Greetings, My copy of the second edition of Chun's "Core Python Programming" just arrived from Amazon on Friday. What really jumped out at me is an interesting feature about how it sequences its topics, namely, (user-defined) functions are not introduced until chapter 11, fully 400 pages into the book. This contrasts strongly with a...
48
2606
by: Tony | last post by:
How much bloat does the STL produce? Is it a good design wrt code bloat? Do implementations vary much? Tony
92
3907
by: ureuffyrtu955 | last post by:
Python is a good programming language, but "Python" is not a good name. First, python also means snake, Monty Python. If we search "python" in google, emule, many results are not programming resource. If we search PHP, all results are programming resource. Second, python also means snake, snake is not a good thing in western culture....
0
7920
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7849
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
1
7973
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
6626
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5394
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3844
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3879
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2358
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
1189
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.