Incrementing operators

Started by
11 comments, last by Zahlman 14 years ago
I noticed that when I enabled nearest neighbor filtering, my textures showed up grayscale. I looked at the code I wrote, which appeared fine:

	ui8 *pix;
	switch(src->format){
		case E_RGB:
		case E_ANIM_RGB:{
			pix = src->data + (src->frameSize * src->currFrame) + 3*(src->width*(_E_mathRoundf(y)) + _E_mathRoundf(x));
			return _E_eoiD1(*(pix++))|_E_eoiD2(*(pix++))|_E_eoiD3(*(pix))|_E_eoiD4(0xFF);
		}
		break;
		...
	}

The _E_eoiDn macros simply shift the passed value to be the nth byte in the integer. To me, it would seem that it would increment the pointer upon each evaluation of the variable. Apparently that isn't the case; the rewrite I wrote below showed the colors properly, rather than only using one channel for all three.

	ui8 *pix;
	si32 result;
	switch(src->format){
		case E_RGB:
		case E_ANIM_RGB:{
			pix = src->data + (src->frameSize * src->currFrame) + 3*(src->width*(_E_mathRoundf(y)) + _E_mathRoundf(x));
			memcpy(&result,pix,3);
			return result|_E_eoiD4(0xFF);
		}
		break;
		...
	}

So, I suppose my question is, if I have multiple incrementing operators on the same variable at different parts of a statement, is it evaluated and incremented more than once in sequence as I'd expected, or does it do all of the increments prior to evaluating the entire expression?
Advertisement
pix++ permanently adjusts the value of pix. So any sucessive access of pix will be of the modified value. They should be incremented in order. But why not just use (pix+1) and (pix+2) then do a pix+=3 at the apropriate time? Seems much more readable that way anyway

-me
pix++ also means: use the value of pix then increment it.
++pix means: increment first then use the value.

But yeah... your statement is ridiculously confusing. Why not something like:

case E_ANIM_RGB:{    pix = src->data + (src->frameSize * src->currFrame) + 3*(src->width*(_E_mathRoundf(y)) + _E_mathRoundf(x));    ui8 r = *pix;    ui8 g = *(pix+1);    ui8 b = *(pix+2);    pix += 3;    return _E_eoiD1(r)|_E_eoiD2(g)|_E_eoiD3(b)|_E_eoiD4(0xFF);}


And also... why are you bitwise or'ing them together?
pix is only twice once during this function; once to initialize, once to be evaluated in this returned expression. I've also read that increment operators require one instruction while adding a constant to a variable requires two. Since this function would be called once or twice for every pixel written for every polygon in my renderer, I figured every little bit counts. But the thing that confused me was, I incremented twice in the expression, and rather than incrementing and using the incremented values, it only used one value, as if it added two and used the last value for all three in the evaluation, or used the first then added two.
don't optimize before your profiler tells you it's a problem. the compiler is better at optimizing than you anyway. your code is confusing and you can't debug it. make it clean with temp variables and trust that the compiler will make it fast. if it doesn't you can always come back and micro-oiptimze it later.

only pre-increment doesn't require a temp. you're doing post-increment. however, that is "old advice". The compiler will almost always optimize this for you.

-me
Quote:Original post by Palidine
pix++ also means: use the value of pix then increment it.
++pix means: increment first then use the value.

But yeah... your statement is ridiculously confusing. Why not something like:

*** Source Snippet Removed ***

And also... why are you bitwise or'ing them together?


That would add(assuming a typical stack), three push instructions to allocate the variables, three to assign them, the usual to reference them, then three to pop them off the stack. And I like to OR them together. On some arch's it is simpler than addition.
Alright, I chose an alternate method, and I'm guessing the compiler added two and used the original value.
Yeah. good plan [smile]

I mean, basically, every piece of advice you've ever heard about arranging code at a micro-level is something that was true maybe 10 years ago. Modern compilers in almost every respect are better than you at that kind of optimization. The only time you should ever worry about details like what you're talking about is if the profiler tells you that piece of code is slow and if you look at the generated assembly and realize that the optimizer has missed something.

-me
Sequence points.
Thank you, BFG, for answering my question. I even remember reading that FAQ a while back. I'll avoid doing that from now on.

This topic is closed to new replies.

Advertisement