开发者

What's the reasoning behind putting constants in 'if' statements first?

开发者 https://www.devze.com 2022-12-18 07:00 出处:网络
I was looking at some example C++ code for a hardware interface I\'m working with and noticed a lot of statements along the following lines:开发者_JAVA技巧

I was looking at some example C++ code for a hardware interface I'm working with and noticed a lot of statements along the following lines:

开发者_JAVA技巧
if ( NULL == pMsg ) return rv;

I'm sure I've heard people say that putting the constant first is a good idea, but why is that? Is it just so that if you have a large statement you can quickly see what you're comparing against or is there more to it?


So that you don't mix comparison (==) with assignment (=).

As you know, you can't assign to a constant. If you try, the compiler will give you an error.

Basically, it's one of defensive programming techniques. To protect yourself from yourself.


To stop you from writing:

 if ( pMsg = NULL ) return rv;

by mistake. A good compiler will warn you about this however, so most people don't use the "constant first" way, as they find it difficult to read.


It stops the single = assignment bug.

Eg,

if ( NULL = pMsg ) return rv;

won't compile, where as

if ( pMsg =  NULL) return rv;

will compile and give you headaches


To clarify what I wrote in some of the comments, here is a reason not to do this in C++ code.

Someone writes, say, a string class and decides to add a cast operator to const char*:

class BadString
{
public:
   BadString(const char* s) : mStr(s) { }

   operator const char*() const { return mStr.c_str(); }

   bool operator==(const BadString& s) { return mStr == s.mStr; }

   // Other stuff...

private:
   std::string mStr;
};

Now someone blindly applies the constant == variable "defensive" programming pattern:

BadString s("foo");

if ("foo" == s) // Oops.  This compares pointers and is never true.
{
   // ...
}

This is, IMO, a more insidious problem than accidental assignment because you can't tell from the call site that anything is obviously wrong.

Of course, the real lessons are:

  1. Don't write your own string classes.
  2. Avoid implicit cast operators, especially when doing (1).

But sometimes you're dealing with third-party APIs you can't control. For example, the _bstr_t string class common in Windows COM programming suffers from this flaw.


When the constant is first, the compiler will warn you if you accidentally write = rather than == since it's illegal to assign a value to a constant.


Compilers outputting warnings is good, but some of us in the real world can't afford to treat warnings as errors. Reversing the order of variable and constant means this simple slip always shows up as an error and prevents compilation. You get used to this pattern very quickly, and the bug it protects against is a subtle one, which is often difficult to find once introduced.


They said, "to prevent mixing of assignment and comparison".

In reality I think it is nonsense: if you are so disciplined that you don't forget to put constant at the left side, you definitely won't mix up '=' with '==', would you? ;)


I forget the article, but the quote went something like:

Evidently it's easier remembering to put the constant first, than it is remembering to use ==" ;))

0

精彩评论

暂无评论...
验证码 换一张
取 消