8 ms·
You also can't test if a pointer points to an element in an array without undefined behavior. C++14 5.6/6, on subtracting pointers: "Unless both pointers point
by forrestthewoods 10y ago
You also can't test if a pointer points to an element in an array without undefined behavior.
C++14 5.6/6, on subtracting pointers: "Unless both pointers point to elements of the same array object or one past the last element of the array object, the behavior is undefined."
http://stackoverflow.com/questions/31774683/is-pointer-comparison-undefined-or-unspecified-behavior-in-c http://stackoverflow.com/questions/31774683/is-pointer-compa...
I wish "undefined behavior" wasn't a thing in C/C++. It's not worth it. :(
- adrianratnapala 10y agoOr rather I wish the standard did not bend over backwards to allow every kind of aggressive optimisation that some compiler writer claims will increase speed of unoptimized code by 0.5%.
- thomasahle 10y agoIsn't that the point of C/C++? "Code should run as fast as the hardware allows" and "We allow you to do crazy things that probably won't be portable, if that's what you want". I wonder, if somebody created a language with C like semantics, like pointer arithmetic, but with a layer in between to ensure consistency and portability.. Would people want to use that, or would the semantics be considered less interesting, when they don't map directly to hardware?
- lmm 10y agoCorresponding directly to the hardware makes sense, sure. But what modern GCC (especially) does goes far beyond that. The intent of signed integer overflow being undefined is that it will be twos complement on a twos complement machine, not that I want half my code to not run if I had an overflow somewhere.
- Sacho 10y agoIf that was the intent, then overflow should have been classified as enumerated implementation-defined behavior, just like the bit representation of an integer type which already deals with those variations.
- caf 10y agoIf that had been the intent, it would have been specified as implementation-defined, not undefined. More likely, the intent was to also accomodate implementations that trapped on overflow.
- jjnoakes 10y agoImplementation-defined includes trapping on overflow.
- lmm 10y ago"Evaluates to an implementation-defined value" would not include that. I'm not sure if any of the usual definitions in the standard includes trapping and doesn't include arbitrary behaviour.
- jjnoakes 10y agoSure, but the standard need not say "Evaluates to an implementation-defined value". There are other wordings which use "implementation-defined" and would support trapping on overflow.
- lmm 10y agoCan you give an example? I struggle to think of anywhere the standard uses a wording that would fit here.
- tehrei 10y agoYeah but with those aggressive optimizations my code doesn't run at all.
- qb45 10y agoThis one is about portability, not optimizations. There are architectures where pointer isn't a simple int, due to things like segmentation, tagging or even possibly something as stupid as lack of sufficiently wide integer type. Heck, there were even C implementations for 36-bit machines, which had 36-bit registers and could only load/store 36-bit-sized and 36-bit-aligned chunks of memory. They packed 4 chars into such word (leaving 4 bits unused) and I don't know how they implemented char* but it must have been something totally mad and not reasonably castable to int or even int*.
- userbinator 10y agobut it must have been something totally mad and not reasonably castable to int or even int.* As long as you can impose an ordering on the elements in memory and thus derive a number for each one, it's possible to define the straightforward representation of a pointer. 4 chars per word is an easy case since you can just let char* be a number with the lowest 2 bits indicating the index within a single word, and the rest of the bits are the word-address. int* can be the same number with the lowest 2 bits always 0. If word addresses are smaller than 36 bits, then values with the higher bits set are invalid, and if they're larger, then use multiple words to hold them. Working with chars on such a machine is going to involve a lot of shifting and otherwise data movement, but there you go, a way to implement C pointers on such a machine.
- qb45 10y ago> int* can be the same number with the lowest 2 bits always 0. And now you have to right-shift int pointers on every dereference for some dubious benefit. It's easier and more efficient to make pointer arithmetic and casting painful.
- adrianratnapala 10y agoNo, you left-shift them on every cast. And is someone type-puns using a union, they get a thing four times samller than they might have expected. Stil it is totally well behaved in a hash.
- _yosefk 10y agoI think you can do that test by comparing pointers, you just can't subtract them. (The SO answer you link to also points out that comparing and subtracting are different, but I'm not sure that what I said follows.) In practice, almost all C and C++ programs depend on both implementation-defined and undefined behavior, and, modulo security implications, that's fine as long as you test the program properly after compiling with a new compiler.
- forrestthewoods 10y agoYou can test equality with a given element. But if you want to test "does this pointer to any element of that array" you can't. As this test would be: bool b = ptr - array_start < array_end - array_start But that first subtraction is undefined if ptr does not point to an element between start and end. Not that this is exactly a common operation or anything. But the fact that a seemingly simple and obvious test is undefined behavior is crazy imo.
- pygy_ 10y agoWhat about array_start <= ptr && ptr < array_end // or `<=` if the upper bound is inclusive Edit: well, for one it may not be thread safe, since it's not atomic, but neither is your example AFAIK.
- nightcracker 10y agoYour edit is pretty much irrelevant - it could be applied to literally any example code anywhere. Unless mentioned otherwise you should assume that all variables are thread-local.
- Sacho 10y agoEvaluating that expression is undefined behavior if ptr is outside the +1 bounds of the array. Check out the enumerated defined behavior in the (old C99, working draft) standard - http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf 6.5.8 Relational operators ...and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values... ... If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P. In all other cases, the behavior is undefined.
- Bromskloss 10y ago> I wish "undefined behavior" wasn't a thing in C/C++. It's not worth it. :( What do you suggest instead? Run-time checks?
- pjmlp 10y agoHave a proper defined behavior like most sane languages. The only reason UB exists was that when ANSI C came to be, the compiler writers and hardware vendors that provided C like compilers didn't want to give up on their semantics. So in order to please everyone, all the semantics that could not be defined on the standard became UB.
- unlinker 10y agoThat is untrue. UB exists because C is supposed to run on so many platforms there is no way to have a defined behaviour for all of them in that standard.
- wongarsu 10y agoMore importantly, C is not only supposed to run on many platforms (many programming languages do that), but also provide very low-level control on wide variety of platforms.
- pjmlp 10y agoWhich people keep forgetting is only available as implementation defined extensions, as such it is no longer ANSI C and any language compiler is free to have extensions.
- jjnoakes 10y agoThis is why implementation defined behavior exists. Undefined behavior though?
- pjmlp 10y agoI was already coding before C had any meaning outside UNIX.
- gpderetta 10y agoYou can do it by converting pointers to integers. No UB, but of course it is implementation defined.
- ArkyBeagle 10y agoUB is unfortunately inherent in the mission statement of 'C'/C++.