Strange pointer decrement behaviour
I just traced a problem with using the decrement operator in a loop which is dependent upon the version of gcc with which you compile the code. WIth the SAFE_VERSION constant definition set to "1" the loop works as expected with gcc 4.3.0:
Code:
#include <stdio.h> Code:
String before = 'abcdefghij'. This did not work with gcc version 4.8.3 which produces the following output: Code:
String before = 'abcdefghij'. |
p-- decrements the pointer, *p-- decrements the value it points to
afaik |
The problem is in your code. The evaluation order of assignments (= and ++) isn't defined by any standard; it is called 'Undefined behaviour'. Another (anti-)example:
Code:
int a= 3; |
Quote:
http://en.cppreference.com/w/c/langu...tor_precedence Notice where is says "right to left" associativity for group 2 in that table. I hope it is obvious what that means. Quote:
There are few and specific constructs in C and C++ for which sequence is defined. The ; ending a statement is the most common/important of those. But otherwise sequence is generally undefined, so when you make any "this happens then that happens" assumptions without a defined sequence point, your code is likely to work by accident rather than by design and then likely to bite you later. In other words what you saw as gcc version "new weirdness" is really your own old bug. Quote:
|
Quote:
anyway, this is interesting to me so il lay it out an equation is variable = expression but there is an operation on the variable and the variable is used to calculate the expression so to deconstruct variable -------------- p = p--; value pointed to by p -------------- expression -------------- p - DELAY; value pointed to by result -------------- according to the table -- is done first - second = third but... p-DELAY is in parentheses so math says it has to be done before any other operation on it's variables so (p-DELAY) becomes a different value to what p-DELAY could give just some thoughts.. |
Quote:
Code:
a = b++; Further down in that page is a link to an "Order of evaluation" page, with some notes on undefined behavior that are relevant. |
Quote:
But now that you said it so clearly for people who already knew it, we are stuck with the problem that people who didn't already know the above also don't know what "bind" means in the above context. I'm don't know how I could both accurately and clearly describe what "bind" means. But the effect is very similar to wrapping () around the operator and its nearest possible operands. so p = p - p--; when we "bind" the -- first we have p = p - (p--); and when we bind the - second we have p = (p - (p--)); In the original *p-- when we bind "right to left" we get *(p--) and then (*(p--)) That is not exactly what "bind" means and you can find cases in C where the extra () implied by a method that crude would mean something else. But to a first level of understanding that is the best definition of "bind" I have. And as you said more clearly, once you've done all that binding, you still haven't determined much about the execution sequence. We know from the binding that the -- applies to p and not to *p, but we don't know whether the memory read operation specified by the * happens before or after the subtract or memory write operations specified by the -- Even in *--p we can know that computing the decremented value happens before the memory read specified by the *, but we still don't know that storing that value back into the variable p happens before that read, and we don't know that the decremented value is computed only once. It might be before and after the *. Code:
char* p; This is the kind of "undefined" operation where a theoretical standard compliant compiler could replace the whole line with code to reformat your hard drive, and even a real compiler may generate code well outside the range of possibilities expected by a naive programmer. |
y my bad, this increment+assign is new to me
i even put it into 2 groups before saying that why even allow increment before equal sign if the variable is used after the equal sign ? p++; *p=*(p-DELAY); would not be prone to interpretation maybe a cc warning would be nice ? |
Hi,
Thanks for all the replies. I am happy just to have traced the problem. Not having studied compilers extensively I must say all this talk of sequences has my head spinning. Quote:
Quote:
Once again I appreciate your discussing this with me. |
Quote:
I think you may be missing the narrowness of the meanings of "value" and "side-effect" in that quote, in thinking that says something significant about sequencing, rather than simply being the meaning that postincrement or postdecrement always had. Quote:
Quote:
Code:
*p-- = *(p - DELAY); That rule says nothing about whether another instance of p on the right hand side is computed before or after that --. |
Quote:
Code:
*p-- = *(p - DELAY); No points for style either. |
Quote:
"request for "undefined evaluation order" warning" ? anyway, thx to johnsfine and rknichols |
Quote:
The sequence point rule is: between consecutive "sequence points" an object's value can be modified only once by an expression. It's the unsequenced access here that is the issue. The value of p is potentially changed by p-- then accessed before hitting the sequence point (the end of the expression). Apologies for muddying the waters. * *This is why I never write code remotely like that. To easy to get something wrong. ---------- Post added 12-04-14 at 01:50 PM ---------- Quote:
|
Quote:
EDIT: Got beat to it. |
Quote:
|
All times are GMT -5. The time now is 10:41 AM. |