?
Solved

C++ Variable Prefixes -- e.g. m_iVariable

Posted on 2003-03-24
7
Medium Priority
?
2,179 Views
Last Modified: 2008-03-03
To all industry experts,

I am a 2nd year college student currently studying computer science.  Now that my basics classes are over, I am starting to develop more complex applications.  I stumbled across generation5.org's wonderful essays on neural networks.  While I was browsing the sample code, I noticed that the programmer(s) chose to prefix all member variables with an "m_" and then, I think, their type -- i,f,c,p,str.  My question is, is this a common practice that I should be getting into the habbit of doing?  I noticed the MFC code generated by Visual C++ uses prefixes, though not those.  If you youself use the prefixes in your code, would you be kind enough to give a list of the ones you use and their meaning (if it isn't obvious).  High points for this question, because 1) it has been bugging me for a while now, and 2) I don't want the so-called experts to pass up this "beginner" question.  Thanks in advance.
0
Comment
Question by:klax33
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 

Expert Comment

by:pcooke
ID: 8196423
There's a lot been written about this. Check out a search for "Hungarian Notation" on MSDN.

Really, it's a matter of style and maintainability.

For example, if I call a variable 'm_i...' I know it is a class member (the m_ bit) and it's an integer type (the i bit).

A variable like 'szFileName' would be a local variable (no m_ bit) and its a zero-terminated string (sz).

There's lots more of these, such as 'p' for a pointer (eg m_pByteArray).

It's a useful way for anybody reading your code (maybe you in six months time) to read a little extra information from the code to help people understand it.

The code would still work if you used variables like 's' or 't' or 'x', but it would be much harder to understand.
0
 
LVL 12

Accepted Solution

by:
Salte earned 1000 total points
ID: 8196494
About prefixes,

In general, don't use them. The idea is that a variable should be declared reasonably close to where you use it and then any prefixes are not necessary.

An exception to this is member variables and there using a prefix of m_ or M_ or _m_ or _M_ is a good idea, the latter ones should be avoided since the compiler implementation usually reserve variables starting with underscore for implementation provided 'system' variables or 'system functions'. The idea is that _x should tell you that x is a variable that is 1. provided by the specific compiler, 2. Is not standard C++ and 3. Is not defined by user code.

However, for exactly this reason you might find compiler provided member variables using _m_ or _M_ as prefix.

Similarly, s_, S_ or _s_ or _S_ can be used to indicate a static member variable (one shared among all objects of the type).

Using prefixes to denote type is generally - in my opinion - a bad idea. Microsoft used it a lot and some people outside of Microsoft also uses it. That still doesn't make it a smart thing to do.

However, if you download some source code written by others that uses prefixes, it is a good idea to also declare prefixes in your own code in that module or modules. The idea is that whenever you modify existing code you should use whatever conventions are used in that code and if you really can't live with that you should rewrite EVERYTHING to suit your own code. Such a rewrite will generally make the code in a state where the person who originally wrote it will not want it back so if you plan to write your contributions to existing code you should use whatever conventions are used in that code.

For code that you write yourself I will advice you to not use prefixes (other than those explained above and a few mentioned below). In particular prefixes to provide type info is really not a good idea. If you need to see the type by seeing a prefix it probably indicate that you have a function that is too large or that the distance between declaration and use of the variable is too large.

However, there are some other prefixes that can be used. I already mentioned the m_ and s_ prefixes. Some people similarly uses g_ to mean 'global variable'. Personally I think that isn't a good idea, the number of global variables outside any classes should be kept at a minimum anyway and so it shouldn't be necessary to prefix those few you have by any particular prefix. However, if you do happen to find that you have a lot you should probably stuff them into a class and if they are then static variables in the class giving them an s_ or S_ prefix rather than giving them all a g_ or G_ prefix.

With the introduction of namespace it is also less need for a prefix to indicate module. However, in some cases this is still useful.

If the code is to be called from old C you don't have namespaces and so have to use prefix.

One problem with namespaces is that people can use 'using namespace foo;' and then omit the 'foo::' prefix and thus you won't know that the function bar() referenced actually was defined in foo unless you are familiar with the contents of the foo namespace. I therefore tend to frown upon excessive use of 'using namespace foo;' declarations and will in general only advice it for std:: (since the contents of that namespace is defined in standard C++ and should be well known).

However, if you really want to make sure that people are always aware of that a function is in foo even if they use 'using' you could give it a 'foo' prefix. However, this is in general better solved by people simply using foo::bar() instead of naming the function foobar() or foo_bar() or something like that.

One exception to all this is if you have a logical class that is split into two actual classes. Logically and conceptually they are one class but due to the implementation you have two separate classes. In this case you can use a common prefix for the methods in the classes to indicate that they really are the same class in a logical manner. Typically in this case you would also have that each A object would have a pointer to the B object if the two classes A and B work together to implement the logical class C. You could perhaps even have a class C that has as it's only members a pointer to an A and a pointer to a B and which implements all its functions through those two pointers. In this case you would NOT use the prefix in the C class and you would probably also mark the two A and B objects as 'internal' in some way so that they can't be used by anyone but C. Typically they would have only private members and have a friend class C;' declaration. In this case you can remove the common prefix since it is a very limited situation and the only one who can call the A::foo() and B::foo() functions is the class C.

So, bottom line is:

m_foo or M_foo is good, s_foo or S_foo is good, _foo means that foo is a non-standard extension provided by the compiler. Don't declare your own variables as _foo.

Btw, if you use m_foo for non-static members you should use s_foo for static members, if you use M_foo for non-static members you should use S_foo for static members.

Most other prefixes are bad and should be avoided unless you have a very good reason to keep them. One such good reason is that the code you're working on already uses them.

Also, since MFC generates code using such prefixes you might end up using them when using MFC. However, use of common sense is the most important guide in all this.

Alf
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 8196572
I think you will find that most programmers use some sort of prefix or suffix for member variables.  Hungarian style notation is fairly widely thought of as a bad thing now.

Take a look at this article for sone of the reasons why:

http://www.cuj.com/experts/1911/hyslop.htm

(you may have to wade through the 'story' bits for useful information, but it is useful all the same).

BTW, If you are looking for good C++ style examples, then MFC is definitely not the place to start - it has been pretty poor C++ for a long time now.  Try something like the boost libraries (www.boost.org) for better examples.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 1

Expert Comment

by:ivec
ID: 8196632
For a nice discussion of the Hungarian-like prefixes you saw by highly regarded experts, see the following article:
 http://www.cuj.com/experts/1911/hyslop.htm

Basically:
 - The type prefixes date back from the K&R C age, where type safety was much weaker than in C++. They do not mix well at all with template code. They also create maintenance problems when using typedefs.
 - The scope prefixes do help in some cases. As in the article, I have actually adopted the underscore as a *suffix* for private data members (using the underscore as a prefix has caveats). Special prefixes for global/static variables can also be useful, but less so in the age of namespaces.

All in all, it all depends on the coding style/conventions you choose. Consistency is all that really matters.
0
 
LVL 12

Expert Comment

by:Salte
ID: 8196841
Jason,

Good story and yes, it sums up my main arguments against hungarian notation pretty well.

I never liked it when it came and it pleases me to see that Microsoft is starting to move away from it. The .net has no hungarian notation.

In particular the 'lp' prefix is really a bad idea. It stands for 'long pointer' and indicates that a pointer is a 'far pointer' as opposed to a 'near pointer'. Since modern 32 bit compilers doesn't use far and near pointers it really is nothing other than a plain 'pointer and so the 'L' in 'LP' is a lie. Still they have to keep it for legacy reasons - it just shows how bad the consequences of hungarian notation is.

Alf
0
 

Author Comment

by:klax33
ID: 8196880
Thanks for all the information guys.  :)  The story link was very useful, though I think the authors should rewrite it to be more like an article instead of a story.  I'll start addeding  m_ and possibly s_ on my next project, but I'll avoid using any others.  Thanks again.
0
 
LVL 12

Expert Comment

by:Salte
ID: 8196943
>> Basically:
>> - The type prefixes date back from the K&R C age, where >> type safety was much weaker than in C++. They do not mix >> well at all with template code. They also create
>> maintenance problems when using typedefs.

Not so sure about that. I don't think either Brian Kernighan nor Dennis Richie used prefixes to indicate type. The hungarian notation for example is a pure microsoft thing and was invented by a hungarian working for Microsoft and the management thought it was a smart idea at the time so they decided that Microsoft should use it in their code. I would believe it was Petzold that made the notation famous outside of Microsoft.

If others have used prefixes other than hungarian notation is probably likely but I doubt it was the creators of C. They were too smart for such silliness. Even in C it really isn't that helpful to use such prefixes to indicate type. In particular since in the very old C you essentially had only one type (int) and even a string was an int (being the address of the first character of the string). The notation would be of small help there, you would generally end up with using i prefix for everything.

As an alternative you could have prefixes to indicate the role a variable play, however, even that is of limited benifit. It is more benificial to use a variable name (and not just a prefix) to indicate role.

>> - The scope prefixes do help in some cases. As in the article, I have actually adopted the underscore as a *suffix* for private data members (using the underscore as a prefix has caveats). Special prefixes for global/static variables can also be useful, but less so in the age of namespaces.

Exactly.

All in all, it all depends on the coding style/conventions you choose. Consistency is all that really matters.

Well, if you are consistently making the wrong choices for variable names/prefixes you will end up with completely unreadable code.

Also, I will tell you to consider NOT using overly long names for variables:

void this_function_call_foo_then_bar_then_loops_a_lot()
{
   foo();
   bar();
   while (gazonk()) {
     bar();
     foo();
   }
   do {
     gazonk();
     bar();
   } while (foobar());
}

err.....

I would say it is a better idea to really figure out what this function is supposed to do on a conceptual level and then give it a name to reflect its overall purpose.

This is in particular ugly if you end up with lots of indentation and then call such a function.

Similarly with variable names except it is even worse then when you try to make an expression:

int variable_to_hold_packet_length = variable_to_hold_the_length_of_data + variable_to_hold_length_of_trailer * number_of_trailers + variable_to_hold_length_of_header * number_of_headers;

I will say that the following code is far more readable and convey just as much information as the expression above:

int packetlength = headerlen * numheaders + datalen + trailerlen*num_trailers;

Also note that the ordering of the terms was changed so that headers are added first, then data then the trailer. This is the natural ordering since this is how the data is layed out in the packet.

Given that the context already provide enough info you can even shorten this to:

int plen = hlen * numh + dlen + tlen * numt;

All in all, provided the reader can easily find what these variables refere to in the immediate vicinity of the code this is the shortest and therefore the most clear and easiest to read.

Alf
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question