C/C++ Post-increment by more than one
I'm r开发者_如何学运维eading bytes from a buffer. But sometimes what I'm reading is a word or longer.
// assume buffer is of type unsigned char *
read_ptr(buffer+(position++))
That's fine but how can I post-increment position by 2 or 4? There's no way I can get the +=
operator to post-increment, is there?
Reason is, I have this big awful expression which I want to evaluate, while at the same time incrementing the position variable.
I think I came up with my own solution. I'm pretty sure it works. Everyone's gonna hate it though, since this isn't very readable code.
read_ptr(buffer+(position+=4)-4)
I will then make this into a macro after testing it a bit to make sure it's doing the right thing.
IN CONCLUSION:
Don't do this. It's just a bad idea because this is the sort of thing that generates unmaintainable code. But... it does turn out to be quite easy to convert any pre-incrementing operator into a post-incrementing one.
how can I post-increment
position
by 2 or 4?
You can't post-increment a variable by 2 or 4 but you can use the following (in your case)
read_ptr(buffer+position); position += 2;
Although, I would not recommend this solution, but if you don't want to change this line in your code:
read_ptr(buffer+(position++));
And you still want to post-increment position
by 2, then define position as Index position(2);
where the type Index
is defined here, and also shown the usage:
struct Index
{
int step;
int value;
Index(int s=1, int v=0): step(s), value(v) {}
Index operator++(int)
{
Index prev(step, value);
value += step;
return prev;
}
operator int() { return value; }
};
int main() {
char arr[] = "1234567890" ;
cout <<"Increment by 2" <<endl;
Index i2(2); //increment by 2
cout << *(arr + (i2++)) << endl;
cout << *(arr + (i2++)) << endl;
cout << *(arr + (i2++)) << endl;
cout << *(arr + (i2++)) << endl;
cout <<"Increment by 3" <<endl;
Index i3(3); //increment by 3
cout << *(arr + (i3++)) << endl;
cout << *(arr + (i3++)) << endl;
cout << *(arr + (i3++)) << endl;
cout << *(arr + (i3++)) << endl;
return 0;
}
Output:
Increment by 2
1
3
5
7
Increment by 3
1
4
7
0
Working Example : http://ideone.com/CFgal
Note: I would still not suggest this solution in real life project. It's more like puzzle :D
The += operator would be a separate statement (not post or pre increment). You could use the following line:
func(buffer + position); position += 2;
You don't; you break it up into more than one line. There is no reason to stuff everything into one line here.
read_ptr( buffer + position );
position += n;
Well, I did answer my question in the edit... Basically what I wanted was a single expression which evaluates to the original value but has a side effect of incrementing by an arbitrary amount. Here are some macros.
#define INC(x,inc) (((x)+=(inc))-(inc))
#define INC2(x) INC(x,2)
#define INC4(x) INC(x,4)
#define INC8(x) INC(x,8)
If position
were a pointer to int16
or int32
, incrementing it would add 2 or 4, respectively.
In C++, you can easily write a function to perform a post-style double-increment:
template <typename T>
T inc2(T &t) {
T r(t);
++t; // or t++ if you want to respect inconsistently-overloaded operators,
++t; // but I wouldn't bother.
return r;
}
read_ptr(buffer+inc2(position))
In C it's slightly more awkward:
size_t inc2(size_t *s) { // or whatever type you're using
size_t r = *s;
(*s) += 2;
return r;
}
read_ptr(buffer+inc2(&position))
You can cover the 4 case as well by making it an additional function parameter, or perhaps an additional template parameter in the C++ case.
There's a second question, whether it's worth pursuing this style of programming in C++ or in C, where you do so much in a single statement. Avoiding side-effects can make the code easier to understand, even though it comes out longer.
A slightly more generalized version of Steve Jessop's answer to accept all kind of increment steps.
template <auto Step>
constexpr auto post_increment(auto& lvalue)
{
auto copy = lvalue;
lvalue += Step;
return copy;
}
If you explicity need to call operator++
instead of operator+=
:
template <auto I>
constexpr auto post_increment_helper(auto& lvalue)
{
lvalue++; // or ++lvalue
if constexpr (I > 1)
post_increment_helper<I - 1>(lvalue);
}
template <auto Step>
constexpr auto post_increment(auto& lvalue)
{
auto copy = lvalue;
post_increment_helper<Step>(lvalue);
return copy;
}
Application :
int a = 4;
auto value = post_increment<5>(a);
std::cout << a << ' ' << value << '\n'; // prints 9 4
精彩评论