For example, suppose you have these variables:
int i = 9;
int j = 7;
Depending on the implementation, the value of, (-i)/j, could be either –1 or –2. How is it possible to get these two different results?
Surprisingly the result is implementation defined in C89:
ANSI draft § 3.3.5
When integers are divided and the division is inexact, if both
operands are positive the result of the / operator is the largest
integer less than the algebraic quotient and the result of the %
operator is positive. If either operand is negative, whether the
result of the / operator is the largest integer less than the
algebraic quotient or the smallest integer greater than the algebraic
quotient is implementation-defined
However this was changed in C99
N1256
§ 6.5.5/6
When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded*
With a footnote:
* This is often called "truncation toward zero"
To clarify, "implementation defined" means the implementation must decide which one, it doesn't mean sometimes you'll get one thing and sometimes you'll get another (unless the implementation defined it to do something really strange like that, I guess).
In C89, the result of division / can be truncated either way for negative operands. (In C99, the result will be truncated toward zero.)
The historical reason is explained in C99 Rationale:
Rationale for International Standard — Programming Languages — C §6.5.5 Multiplicative operators
In C89, division of integers involving negative operands could round upward or downward in an implementation-defined manner; the intent was to avoid incurring overhead in run-time code to check for special cases and enforce specific behavior. In Fortran, however, the result will always truncate toward zero, and the overhead seems to be acceptable to the numeric programming community. Therefore, C99 now requires similar behavior, which should facilitate porting of code from Fortran to C.
Related
I am doing a bitwise left shift operation on negative number.
int main(void) {
int count = 2;
printf("%d\n", ~0<<count);
printf("%d\n", ~0<<2); // warning:shifting a negative signed value is undefined [-Wshift-negative-value]
return 0;
}
My doubt is why the warning is coming on compiling above code when integer literal is used in shifting and not when variable is used.
Under C89, ones'-complement and sign-magnitude implementations were required to process left shifts of negative values in ways that may not have been the most logical on those platforms. For example, on a ones'-complement platform, C89 defined -1<<1 as -3. The authors of the Standard decided to correct this problem by allowing compiler writers to handle left shifts of negative numbers in any way they saw fit. The fact that they allowed that flexibility to all implementations including two's-complement ones shouldn't be taken to imply that they intended that two's-complement implementations to deviate from the C89 behavior. Much more likely, they intended and expected that the sensible behavior on two's-complement platforms would be sufficiently obvious that compiler writers would figure it out with or without a mandate.
Compilers often squawk about left-shifting negative constants by other constants because x<<y can be simplified when both x and y are constants, but such simplification would require performing the shift at compile time whether or not the code containing the shift is executed. By contrast, given someConstant << nonConstant, no simplification would usually be possible and thus the compiler would simply generate code that does the shift at run-time.
I took a quiz in my CS class today and got a question about the modulo operator wrong because I didn't know about the availability of % in C, I've been using fmod(). Why do both exist? Is one better/faster or do they just deal with different data types?
modulo division using % operator in C only works for integer operands and returns an integer remainder of the division.
The function fmod accepts double as arguments meaning that it accepts non-integer values and returns the remainder of the division.
Additional note on fmod: how is the remainder calculated in case of double operand? Thanks #chux for showing the documentation on how fmod calculates the remainder of a floating point division.
The floating-point remainder of the division operation x/y calculated
by this function is exactly the value x - n*y, where n is x/y with its
fractional part truncated.
The returned value has the same sign as x and is less or equal to y in
magnitude.
On the other hand, when the modulo division binary operator (%) was first designed, it was determined by the language designers that it would only support operands of 'integer' types because technically speaking, the notion of 'remainder' in mathematics only applies to integer divisions.
It's because % is an integer operator, and fmod stands for floatmod and is used for floating point numbers.
Why do both exist?
Because they may have computed different results, even with the same values. These differences may occur with negative values. In essence fmod() and % were different mathematical functions.
fmod(x,y), since C89, had the result "the result has the same sign as x and magnitude less than the magnitude of y".
i%j was not so singularly defined. See Remainder calculation for the modulo operation. This allow code to use existing variant processors effectively. The div() function was created to address this variability. Ref
By C99 they compute the same for the same values. Future C could allow 123.4 % 56.7
% is just integer modulo
fmod is float modulo and can be used as described in MSDN.
https://msdn.microsoft.com/en-us/library/20dckbeh.aspx
I'm using QAC and I get the below message for the respective source code line. How can I cast it in order for QAC to "understand" it ?
Compiler used is gcc - it doesn't warn about this issue, as it is set to "iso c99".
#define DIAGMGR_SIGNED_2_BYTES_178 ((s16)178)
sK = (s16)(sE1 / DIAGMGR_SIGNED_2_BYTES_178);
^
Result of signed division or remainder operation may be implementation
defined
.
A division ('/') or remainder ('%') operation is being performed in a
signed integer type and the result may be implementation-defined.
Message 3103 is generated for an integer division or remainder
operation in a signed type where:
One or both operands are non-constant and of signed integer type, or
Both operands are integer constant expressions, one of negative value and one of positive value
A signed integer division or remainder operation in which one operand
is positive and the other is negative may be performed in one of two
ways:
The division will round towards zero and any non-zero remainder will be a negative value
The division will round away from zero and any non-zero remainder will be a positive value In the ISO:C99 standard the first approach is
always used. In the ISO:C90 standard either approach may be used - the
result is implementation defined. For example:
/PRQA S 3120,3198,3408,3447 ++/
extern int r;
extern int si;
extern void foo(void)
{
r = -7 / 4; /* Message 3103 *//* Result is -1 in C99 but may be -2 in C90 */
r = -7 % 4; /* Message 3103 *//* Result is -3 in C99 but may be 1 in C90 */
si = si / r; /* Message 3103 */
}
You need to configure the tool so that it understands that your code is C99. In the old C90 standard, division with negative numbers could be implemented in two different ways, see this. This was a known "bug" in the C90 standard, which has been fixed since C99.
This is a standard warning for most static analysis tools, particularly if they are set to check for MISRA-C compliance. Both MISRA-C:2004 and 2012 require that the programmer is aware of this C standard "bug".
Work-arounds in C90:
If you know for certain that the operands aren't negative, simply cast them to unsigned type, or use unsigned type to begin with.
If you know that the operands might be negative:
If either operand is negative, set flags to indicate which one(s) it was.
Take the absolute values of both operands.
Perform division on absolute values.
Re-add sign to the numbers.
That's unfortunately the only portable work-around in C90. Alternatively you could add a static assertion to prevent the code from compiling on systems that truncate negative numbers downwards.
If you are using C99, no work-arounds are needed, as it always truncates towards zero. You can then safely disable the warning.
I use the codeblock.
When the code is:
printf("%d",1/0);
The program can not run, there is an error. But when I write this:
printf("%d",1/0.0);
The program can run,and the output is 0. I want to know why.
1/0 or 1/0.0 are both undefined behavior:
C11 §6.5.5 Multiplicative operators
The result of the / operator is the quotient from the division of the first operand by the
second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.
You are invoking undefined behavior of two different forms one by dividing by zero, the draft standard section 6.5.5 Multiplicative operators paragraph 5 says (emphasis mine):
The result of the / operator is the quotient from the division of the first operand by the
second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.
The second by using the wrong format specifier in printf, you should be using %f since the result of 1/0.0 is a double not an int. The C99 draft standard section 7.19.6.1 The fprintf function which also covers pritnf in paragraph 9 says:
If a conversion specification is invalid, the behavior is undefined.248) If any argument is not the correct type for the corresponding conversion specification, the behavior is
undefined.
Although if the implementation supports IEEE 754 floating point division by zero should result in either +/- inf. and 0/0.0 will produce a NaN. Important to note that relying on __STDC_IEC_559__ being defined may not work as I note in this comment.
In theory, the result of 1/0.0 may be undefined in a C implementation, since it is undefined by the C standard. However, in the C implementation you use, the result is likely infinity. This is because most common C implementations use (largely) IEEE 754 for floating-point operations.
In this case, the cause of the output you see is that 1/0.0 has double type, but you are printing it with %d, which requires int type. You should print it with a specifier that accepts the double type, such as %g.
I seem to remember that ANSI C didn't specify what value should be returned when either operand of a modulo operator is negative (just that it should be consistent). Did it get specified later, or was it always specified and I am remembering incorrectly?
C89, not totally (§3.3.5/6). It can be either -5 or 5, because -5 / 10 can return 0 or -1 (% is defined in terms of a linear equation involving /, * and +):
When integers are divided and the division is inexact, if both operands are positive the result of the / operator is the largest integer less than the algebraic quotient and the result of the % operator is positive. If either operand is negative, whether the result of the / operator is the largest integer less than the algebraic quotient or the smallest integer greater than the algebraic quotient is implementation-defined, as is the sign of the result of the % operator. If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.
C99, yes (§6.5.5/6), the result must be -5:
When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded.88) If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.
88) This is often called "truncation toward zero".
Similarly, in C++98 the result is implementation defined (§5.6/4), following C89's definition, but mentions that the round-towards-zero rule is preferred,
... If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined74).
74) According to work underway toward the revision of ISO C, the preferred algorithm for integer division follows the rules defined in the ISO Fortran standard, ISO/IEC 1539:1991, in which the quotient is always rounded toward zero.
and indeed it becomes the standard rule in C++0x (§5.6/4):
... For integral operands the / operator yields the algebraic quotient with any fractional part discarded;82 ...
82) This is often called truncation towards zero.
To add a little detail to KennyTM's answer: If the C Standards call something implementation defined then that implementation is required to document the choice it makes. Usually this would be in the compiler or library documentation (man page, help manual, printed docs, CD booklet :-)
Any implementation claiming conformance to C89 or later must provide this somewhere.
Try looking for such a document. In the case of gcc for example, this is in the gcc-info:
4 C Implementation-defined behavior
A conforming implementation of ISO C is required to document its
choice of behavior in each of the areas that are designated
"implementation defined". The following lists all such areas, along
with the section numbers from the ISO/IEC 9899:1990 and ISO/IEC
9899:1999 standards. Some areas are only implementation-defined in one
version of the standard.
Some choices depend on the externally determined ABI for the platform
(including standard character encodings) which GCC follows; these are
listed as "determined by ABI" below. *Note Binary Compatibility:
Compatibility, and `http://gcc.gnu.org/readings.html'. Some choices
are documented in the preprocessor manual. *Note
Implementation-defined behavior: (cpp)Implementation-defined behavior.
Some choices are made by the library and operating system (or other
environment when compiling for a freestanding environment); refer to
their documentation for details.
Menu:
Translation implementation::
Environment implementation::
Identifiers implementation::
Characters implementation::
Integers implementation::
Floating point implementation::
Arrays and pointers implementation::
Hints implementation::
Structures unions enumerations and bit-fields implementation::
Qualifiers implementation::
Declarators implementation::
Statements implementation::
Preprocessing directives implementation::
Library functions implementation::
Architecture implementation::
Locale-specific behavior implementation::