Jump to content
  • Advertisement
Sign in to follow this  
n00body

Pixel swapping trick [SOLVED]

This topic is 3750 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

In the most recent NeHe lesson, TGA loading, they handle BGR -> RGB using this trick: color[0] ^= color[2] ^= color[0] ^= color[2]; What advantages does this approach have, when compared to a more general: temp = color[0]; color[0] = color[2]; color[2] = temp; Thanks for your input. [Edited by - n00body on July 16, 2008 8:56:07 PM]

Share this post


Link to post
Share on other sites
Advertisement
It has the advantage of being less readable and pretentiously clever... oh wait.

In other words, don't do what NeHe does here. It has no advantages.

Share this post


Link to post
Share on other sites
Quote:
Original post by n00body
In the most recent NeHe lesson, TGA loading, they handle BGR -> RGB using this trick:
color[0] ^= color[2] ^= color[0] ^= color[2];

What advantages does this approach have, when compared to a more general:
temp = color[0];
color[0] = color[2];
color[2] = temp;


Thanks for your input.


Other than not having to allocate space for the temp variable (a minuscule amount), none.
If you're given a programming test and you're asked how to swap two variables without a third temporary variable, you'll know how. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by n00body
color[0] ^= color[2] ^= color[0] ^= color[2];

This is actually undefined behavior because you're modifying those variables multiple times between sequence points.

The correct code for the XOR swap is the following:
color[0] ^= color[2];
color[2] ^= color[0];
color[0] ^= color[2];

Share this post


Link to post
Share on other sites
Quote:
Original post by Ra
Quote:
Original post by n00body
color[0] ^= color[2] ^= color[0] ^= color[2];

This is actually undefined behavior because you're modifying those variables multiple times between sequence points.


Mind elaborating for the less understanding [embarrass]? The way I see it, you get right-associativity and the behaviour is well-defined as a ^= (b ^= (a ^= b)).

Share this post


Link to post
Share on other sites
IRC logs just now, I'll edit this post to try and trim out the noise in a moment:

Quote:
[18:20] <ra> color[0] ^= color[2] ^= color[0] ^= color[2]; <-- isn't this UB?
[18:21] <ra> the variables are being modified multiple times between sequence points
[18:21] <ra> because ^= is not a sequence point, right?
[18:21] <MaulingMonkey> ra, fuck yes it isn't
[18:21] <MaulingMonkey> So, yeah, UB.
[18:21] <_kw> ...
[18:22] <MaulingMonkey> Nope, you're wrong, _kw
[18:22] <_kw> how is that wrong?
[18:22] <MaulingMonkey> Operator precidence only affects how the expression is parsed
[18:22] <MaulingMonkey> That is, color[0] ^= (color[2] ^= color[0]);
[18:22] <jpetrie> Indeed.
[18:22] <jpetrie> Modification of the same value multiple times between sequence points. Undefined.
[18:23] * PlacidBox looks up a list of sequence points again
[18:23] <MaulingMonkey> ^= does not count as a sequence point, however, and thus this statement violates the rule in C++ that an integral type such as int cannot be read in the same expression that it is modified without an intervening sequence point.
[18:23] <MaulingMonkey> If you consider the expression:
[18:23] <MaulingMonkey> a() = b() = c()
[18:23] <MaulingMonkey> The C++ standard states that a, b, OR c can execute first.
[18:23] <MaulingMonkey> Because there are no sequence points.
[18:23] <MaulingMonkey> Thus, it's entirely valid for a() to be called first, then c(), then b()
[18:24] <MaulingMonkey> And similar fucked up situations.


Quote:
[18:24] <_kw> but for example, a = b = 7;
[18:24] <_kw> there b=7 is executed first
[18:24] <_kw> and returns 7
[18:24] <_kw> or evaluates to 7 even
[18:25] <ra> _kw, for a = b = 7; it's a = (b = 7);
[18:25] <MaulingMonkey> But, the important part is that it results in 7
[18:25] <MaulingMonkey> b = a = b = 7 is undefined behavior
[18:25] <MaulingMonkey> Now, in that statement, b may or may not be assigned to 7 immediately.
[18:26] <MaulingMonkey> As in, before a is assigned to it.
[18:26] <notWtf> wtf, b = a = b = 7 is undefined behavior ???
[18:26] <_kw> a=b=7; is defined, but b=a=b=7 is undefined? :-/
[18:26] <jpetrie> Yes.
[18:26] <MaulingMonkey> notWtf: Two modifications of a single pod [simple types such as plain structs, ints, pointers, etc --MM] between sequence points, yes, very illegal
[18:26] <_kw> wtf..
...
[18:26] <notWtf> MaulingMonkey: well if things work in the correct order, like left to right, whats wrong
[18:27] <MaulingMonkey> notWtf: They don't always.
[18:27] <notWtf> orly
[18:27] <MaulingMonkey> notWtf: In fact, it usually varies by compiler.
[18:27] <MaulingMonkey> Consider:
[18:27] <MaulingMonkey> std::cout << ++i << ++i << ++i;
[18:27] <MaulingMonkey> This tends to spit out different values depending on your compiler.
[18:27] <MaulingMonkey> If i was 0, for example,
[18:27] <MaulingMonkey> It may print 1 2 3
[18:27] <MaulingMonkey> 3 3 3
[18:27] <MaulingMonkey> 3 2 1
[18:27] <MaulingMonkey> or 1 1 1


Full unedited logs in non-forum-breaky format

Share this post


Link to post
Share on other sites
color[0] ^= color[2] as a subexpression appears twice in that statement. That means color[0] is assigned to twice in that statement.

There are no sequence points in that statement but for the trailing semicolon.

Thus, color[0] is assigned (written) twice before any sequence point.

The C++ standard says that the modification of a value more than once between sequence points is undefined behavior.

Thus, the expression is undefined behavior.

Share this post


Link to post
Share on other sites
Quote:
Original post by agi_shi
Quote:
Original post by Ra
Quote:
Original post by n00body
color[0] ^= color[2] ^= color[0] ^= color[2];

This is actually undefined behavior because you're modifying those variables multiple times between sequence points.


Mind elaborating for the less understanding [embarrass]? The way I see it, you get right-associativity and the behaviour is well-defined as a ^= (b ^= (a ^= b)).

Even with right-associative evaluation (which isn't necessarily the case per the standard) you're invoking undefined behavior because the values of a and b are modified more than once between sequence points (usually ;--there are other possible sequence points but none are present in this example unless a and b are user-defined types with overloaded ^= operators).

Share this post


Link to post
Share on other sites
A note I missed elaborating on:

I give some examples of what undefined behavior could do. Please be aware that in general, undefined behavior can be much worse. You know one of the most common security holes -- buffer overflows -- those things that silently crash your program hours later, or worse, let an attacker inject random code into your servers to be executed?

This happens because in C++, accessing beyond the end of an array constitutes -- you guessed it -- undefined behavior.

Executing a program compiled by a conforming C++ compiler (of which there are none that perfectly do) that invokes undefined behavior may legally launch nuclear missiles at a cow ranch in Alaska. I'm under the impression that, as half-joke, a version of GCC at one point would cause the program to launch the game nethack when invoking certain forms of undefined behavior.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!