jacob navia said:
Le 29/12/10 22:51, Keith Thompson a écrit :
jacob navia said:
Le 29/12/10 15:34, christian.bau a écrit : [...]
What _precisely_ is the semantics of the "_overflow" function?
It returns 1 if the last operation overflowed, zero if not.
Concerned operations: signed +,-,*, and /.
What about shift operators? ++?
Included if signed
--?
Included if signed
Conversions?
Overflow should be detected in conversions.
Array indexing?
Depends if the index is signed or not.
What does that mean? I'm referring to the indexing operation itself,
not to the computation of the index.
Should be detected of course. If
0xFFFFE + 0x100 overflows it gives a bad address.
Ok, what does "overflows" mean for a pointer? If a pointer addition
yields an address outside the bounds of the object to which it points,
is that an overflow, or does overflow occur only if the resulting
address is actually invalid? The same applies to array indexing,
which is of course defined in terms of pointer arithmetic.
That is trapped anyway in most machines.
Yes, I know that. That doesn't mean a portable program can respond
to a trapped division by 0. Does your _overflow() or something
similar handle division by 0, or do you only handle overflow?
Oh, and you said "signed"; does that mean it applies only to
integer operations, or does it also cover floating-point?
The last operation. Can't you understand english?
Don't be insulting.
Last operation in this context means any of the four
operations where the operands are signed. I hope
I do not have to explain to you hat "last" means.
Yes, as a matter of fact you do.
Note that it can be impossible to know how the compiler
will schedule operations in complex expressions,
so to have good results it is better to test operations
individually.
And that's exactly what I was asking about. If there are multiple
operations in an expression, and the language doesn't define the
order of evaluation, which one is the "last"? Is it undefined?
Does _overflow() tell you whether one arbitrarily chosen recent
operation overflowed? Is the behavior undefined?
If you're defining a language feature, it's not enough to say that
it *should* be used only in certain simple ways. You need to define
its behavior in all cases, or clearly state the cases in which its
behavior is undefined, unspecified, or implementation-defined.
Another case to consider:
x = y + z; /* might overflow */
puts("hello");
if (_overflow()) {
/* ... */
}
If you're going to remove the no-argument _overflow() and replace
it with something that takes the expression as an argument, you can
ignore this.
[...]
What bothers me is that you seem so upset that I offer a SOLUTION
instead of just allowing UB. Maybe you can offer a BETTER solution?
I am all ears.
Nobody is upset with you for offering a solution. We are offering
criticisms of the solution you're offering. If you don't want
criticism, I suggest not posting here. (That last was not meant
seriously; what I actually suggest is that you post here *and*
accept criticism.)
I have always accepted good ideas. Mr Bau proposed
int _overflow(int expr);
You would write:
if (_overflow(a+1000)) {
}
for instance. I think that is an even better solution than mine. If
I have time I will implement it.
Yes. I independently proposed the same thing in this thread,
before I read Mr. Bau's article. I also suggested something similar
nearly 4 months ago, in message <
[email protected]>:
| Here's a thought:
|
| bool overflowed = false;
| int x = _CHECKED(overflowed, y + z);
| if (overflowed) {
| ...
| }
|
| The idea is that _CHECKED is a macro that takes two arguments,
| an lvalue that refers to a bool object, and a subexpression to be
| evaluated with overflow checking. If an overflow occurs anywhere
| within the expression, the bool is set to true and the resulting
| value is unspecified (but not a trap representation). Otherwise,
| the bool is either set to false or left alone, and the macro
| invocation yields the result of the subexpression. The definition
| of the macro presumably requires compiler magic.
This is more complex than _overflow(expr), but it has the advantage
that it yields the result of the expression *and* tells you whether
it overflowed or not, whereas _overflow(expr) presumably discards
the result of the expression.
I don't expect you to acknowledge that I might have proposed
something useful.