(well a report in TOPLAS really, but that's pretty close)
There are technically 5 different versions of this operation, though only 2 (possibly 3) are in common use. Common Lisp seems to implement all of them except, somewhat oddly, the euclidean version (the "actual modulo"), its mod function is instead a flooring division.
edit: it looks like Python also follows flooring, not euclidean, meaning the quotient is rounded downwards, and per "a = nq + r" the remainder has the sign of the divisor:
>>> 5 % -2
-1
>>> divmod(5, -2)
(-3, -1)
The C version is the "truncating" division, meaning the quotient is truncated (rounded towards 0).Why? Mathematically, dividing two integers yields a real. If you want the result to be an integer, you need to define some rounding operation on the real result to produce an integer.
That is the source of the divergence between C and Python here, C rounds by truncation (towards 0), Python rounds by flooring (towards -inf).
We both know that's not true.
> Sorry. (I got the terms for quotient, dividend, and divisor mixed up.)
No big, brainfarts happen.
Rational, more specifically.
not true. if you define 'divide' as inverse multiplication over the reals then that is closer to being true (zero is an integer, dividing an integer by zero doesn't yield a real). in that case every real can be expressed as n = a/b where a and b are integers and b != 0 then yes n is a real.
But 'divide' could just as well be defined along the lines of divisibility in number theory (the study of integers) where every integer can be expressed as n = q*b + r, where n,q,b,r are all integers and r >= 0 > b. then you could say that n divide b = q, with r as remainder, and n mod b = r. These are my preferred definition of mod and integer division.
Of interesting mathematical consequence, each of my children converged on the same solution at different ages. Them: three cookies. Daddy: zero cookies.
After thinking about this, what I really want is a way to access an array with an unadjusted number and tell the array to do whatever modulizing is necessary. e.g. instead of
a[small]
a[mod1(big)]
I'd like to have something more like a{small}
a[big]But I don't get how this would practically work. Would each array have a preferred n that is used for the mod operation? For most situations where that makes sense, using a 2d array seems more logical.
I assume the braces are there for "I want to skip doing the wrapping"
Now, having refined the type this way, when you try elsewhere in the code to read some unknown byte into n, WUFFS will reject that because who knows if it exceeds 40? To make the code compile, you need to actually write code that ensures n is always less than 40.
Of course you aren't going to write big general purpose software under this sort of constraint, it's like having a two year old following you everywhere insisting on a detailed explanation of why you are doing every single thing and asking the most irritating "But why?" questions after each explanation, exhausting. But if you're processing untrusted data it's exactly what you needed to stay safe.
https://stdlib.ponylang.io/builtin-Integer/#div_unsafe
and, in Ponylang, i/0 usually results in 0.
That said, I do feel that Pony should have added a 'panic' concept and then forced actors to handle panics, but that's me.
It's not completely untenable, but it's still kinda janky. I've never heard of any mathematical argument that justifies division by zero yielding 0; contrast 0^0, which at least has an argument for yielding 1: http://mathscitech.org/articles/zero-to-zero-power
0/x = 0 for all x except zero; defining 0/0=0 removes that exception.
(Caveat: I’m probably being slightly imprecise with my language here)
In the majority of these cases the most reasonable answer is 0.
> The binary arithmetic operators are +, -, *, /, and the modulus operator %.
https://archive.org/details/TheCProgrammingLanguageFirstEdit...
At least, that was the C reference I used in college.
It goes on to say: "x % y produces the remainder when x is divided by y" and that "the sign of the result for % are machine-dependent for negative operands, as is the action taken on overflow or underflow".
You will find "modulus operator" to refer to % in C in all of the above (other than the standard).
edit: tertiary -> ternary
Calling it "Ayers Rock" privileges some guy from the 19th century, calling it "Uluru" privileges a bunch of people who lived near it for longer than that, the rock itself has no opinion (and also doesn't believe anything about ritual magic, property law, gender based taboos, or the tourist industry)
Now, John Carmack is a little different because John is a person and it is rude to use names people don't like. But it isn't impossible, it's just rude. Calling the previous President of the United States of America "Tangerine Palpatine" works just fine - we both know who I meant. In fact it's a little weird that our culture has parents assign to their children full legal names, only kinda-sorta making it possible for them to choose for themselves later, the Culture's habit of allowing children to pick one of their names as part of growing up seems better.
The more something gets repeated from person to person, the higher chance that somewhere in that chain, somebody screwed up. That's why people like professors, people who run YouTube programming channels, people who answer C questions on Stack Overflow, etc. should generally strive to cut down the number of links in the chain.
The draft version "X3.???-1988" at https://web.archive.org/web/20161223125339/http://flash-gord... (linked-to from Wikipedia) has:
> % modulus operator: 3.3.5
which seems off to a good start for K&R, but then also has:
> remainder operator, %, 3.3.5
and 3.3.5 says "the result of the % operator is the remainder" -- not a whiff of a modulus present there.
Thanks!
The binary operator / indicates division. When positive integers are divided, truncation is toward 0, but the form of truncation is machine-dependent if either operand is negative. On all machines covered by this manual, the remainder has the same sign as the dividend. It is always true that (a/b)*b + a%b is equal to a (if b is not 0). The binary % operator yields the remainder from division of the first operand by the second.
Are C programmers still using C89 and C90?
The C compilers supplied by microcontroller vendors in particular are often, to put it charitably, not great at conforming with the latest standards.
EDIT: Fact checking myself, I found [1], so apparently they've decided to start adding C11 and C17. C99 support isn't entirely clear, though.
[1] https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-...
A parallel can be drawn to `export template` in C++98, which is a feature that was only ever implemented by a single compiler (whose engineers, when asked for recommendations to others attempting to implement, offered "don't"). As a result, it was dropped from later versions of the standard, and so almost every compiler doesn't actually support C++98 100%, but no one cares because the things that it doesn't implement doesn't matter. VLAs aren't quite as universally maligned as `export template`, but given that it's dropped to optional in later versions, it's not totally unreasonable to claim implementation of all of C99 that matters while not supporting VLAs.
Answering my own question: by doing a binary search on the online GCC documentation, I discovered that it's not documented up to 4.2.4. The next version up for which online documentation is hosted is 4.3.6, and that has -Wvla.
Naturally removing them from ISO C was the saner option.
VLA's crept in to the kernel, which is what this thread is about.
With -Wvla, you can learn about where all the VLA's are being declared in the code base.
Also, don't forget that VLA's are a GCC extension which existed before C99. They are available in the -stdc=gnu89 mode, and -ansi (without -pedantic).
They are available in -ansi mode (diagnosed if you use -pedantic).
They were not "removed" from ISO C; they are optional. If you implement VLA's, there is an ISO-C-conforming way to do that.
$ cat vla.c
int fun(int x, int a[x]) { return 0; }
int main(void) { return 0; }
$ gcc -ansi vla.c
$ gcc -std=gnu89 vla.c
$ gcc -ansi -pedantic vla.c
vla.c:1:1: warning: ISO C90 forbids variable length array ‘a’ [-Wvla]
int fun(int x, int a[x]) { return 0; }
^~~
$ gcc -std=gnu89 -pedantic vla.c
vla.c:1:1: warning: ISO C90 forbids variable length array ‘a’ [-Wvla]
int fun(int x, int a[x]) { return 0; }
^~~
This warning is now linked to [-Wvla] rather than just [-pedantic], so you can have -pedantic on, yet allow VLA's without a diagnostic. $ gcc -std=gnu89 -pedantic -Wno-vla vla.c
$ gcc -ansi -pedantic -Wno-vla vla.c
Likewise you need -Wvla to police your code against VLA's creeping in, even if you're compiling in -ansi/-std=c90 mode. Traditionally, -pedantic will do it, but it's too strong; it rejects other things you might want. For instance, in the gnu89 dialect, you can initialize local structs and arrays with non-load-time computable expressions, which is complained about with -pedantic.Dynamic allocation from the stack is something that is quite essential in some situations, and a more efficient approach compared to other alternatives in some other situations.
alloca never goes away, and VLA's are better than alloca in many ways.
You can discuss your point of view with the folks that cleaned the kernel.
https://lore.kernel.org/all/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK...
Notice that they are fully aware of that warning.
I don't know what point of view you're talking about; what the are discussing in the mailing list are silly uses of VLA that can be replaced by small arrays of fixed length sized to the worst case. These perform better, too.
This is not always practical in every situation.
C itself dynamically allocates from the stack. When a function is called, the increment in stack usage depends on which function. (If recursion is going on, it may not be easy to know the worst-case stack size, even if every function has a static frame size.)
Anyway, similarly, suppose we have used C to write a virtual machine. Suppose the virtual machine allocates function locals and temporaries on the native stack. When a VM function call is processed, the VM (a C program) has to allocate a frame for that. a VLA or alloca can provide that easily, with minimal waste.
> Anyway, some of these are definitely easy to just fix, and using VLA's is actively bad not just for security worries, but simply because VLA's are a really horribly bad idea in general in the kernel.
Code running in the kernel has a limited stack space. I think it's tiny, something like just a few pages.
Interrupts (which can nest) run in that stack space, not just the mainline code in syscall context. I think that might have changed though (there are interrupt specific stacks), which might also depend on the specific arch port of Linux. Still, those stacks are small and all the caveats apply to interrupt context. Don't be searching a linked list with linear recursion or using crazy VLA's.
If I had to put virtual machine execution into the kernel, though, I would definitely use VLA's or alloca to get the space required for each function to be as tight as possible to its actual requirements, the same way that the C compiler emits code for each function to allocate its frame size to exactly the needed size. Right tool for the right job.
Postgres only updated to C99 with PG12
https://www.postgresql.org/docs/11/source-conventions.html https://www.postgresql.org/docs/12/source-conventions.html
Some blame to be had by MSVC, which is called out in PEP7: https://www.python.org/dev/peps/pep-0007/#c-dialect
Why insist on MSVC when it's not one of them?
(Genuine question. I remember python was c89 for similar reasons).
Incidentally, that’s around the same time MSVC started getting updates and became bearable.
Why is a drop in replacement for MSVC needed?
There were c99 compilers for windows before clang IIRC correctly. So why weren't they used, MSVC be damned?
Full disclaimer, I've only ever used C in linux systems.
It seems that only GCC 4.3 added the -Wvla option to unbundle the diagnosis of the presence of VLA's from -pedantic.
Now you can write in gnu89, while banishing VLA's from your code base, if you're so inclined.
That just makes C look worse. Remainders are always nonnegative, as specified in the Division Algorithm [note that the Division Algorithm is the name of a theorem, not an algorithm].
https://en.wikipedia.org/wiki/Euclidean_division
Also, I'm not aware of a definition of "modulo" other than "remainder". Where are you getting the idea that they're different?
For example, https://en.wikipedia.org/wiki/Modulo_operation explicitly defines "modulo" as "remainder".
> a mod b = ((a % b) + b) % b
The first remainder bounds it to -b < x < b. Then adding b goes to 0 < x < 2b. Then the second remainder gets th desired 0 <= x < b.
This will not work for b > max_int / 2 (solution in that case is much mkre language dependent)