Navigation



2.9 — Hungarian Notation

Hungarian Notation is a naming convention in which the type and/or scope of a variable is used as a naming prefix for that variable. For example:

int value; // non-Hungarian
int nValue; // the n prefix denotes an integer

double width; // non-Hungarian
double dWidth; // the d prefix denotes a double

Hungarian Notation was invented in 1972 by Charles Simonyi, a Microsoft programmer. The original idea of Hungarian Notation was to encode information about the variable’s purpose, which is known as Apps Hungarian. Over time, this focus changed to encoding information about the variable’s type and/or scope, which is known as Systems Hungarian.

There is a lot of controversy over whether Hungarian Notation is useful in modern programming languages and with modern IDEs. We believe the advantages still outweigh the disadvantages, though you will find plenty of programmers who disagree.

One advantage of Hungarian Notation is that the variable type can be determined from it’s name. Many argue that this is an obsolete advantage, because most modern IDEs will tell you a variables type if you mouse-hover over the name. However, consider the following snippet:

float applesPerPerson = totalApples / totalPersons;

Casually browsing the code, this statement would probably not attract notice. But there is a good chance it’s wrong. If totalApples and totalPersons are both integers, the compiler will evaluate totalApples / totalPersons using integer division, causing any fractions to be lost before the value is assigned to applesPerPerson. Thus, if totalApples = 5, and totalPersons = 3, applesPerPerson will be assigned 1 instead of the expected 1.66!

However, if we use Hungarian Notation variable names:

float fApplesPerPerson = nTotalApples / nTotalPersons;

The n prefixes make it clear from just browsing the code that this is an integer division that’s going to cause us problems! Furthermore, as you code, the n prefix will remind you to watch out for integer division and overflow issues every time you use an integer variable in an expression or statement.

Another advantage of Hungarian Notation is that it gives us a way to name variables using shorthand. For example, bError is understood to mean isError, and nApples is a shorthand way of writing numberOfApples.

One perceived disadvantage of Hungarian Notation is that it leads to extra work when a variable’s type changes. For example, it is common to declare an integer variable and then later change it to a double variable because you need to deal with fractional values. Without using Hungarian Notation, you could change int value to double value and go on your merry way. However, in Hungarian Notation, you’d not only have to change the declaration int nValue to double dValue, you’d have to change every use of nValue in your entire program to dValue! If you do not, your naming scheme will be misleading and inconsistent.

While replacing a potentially huge number of variable names is certainly a nuisance, we believe it is also a good thing. Because different types have different behaviors, having to explicitly replace your variable names encourages you to examine your code to ensure you’re not doing anything dangerous with the new type.

For example, without Hungarian Notation, you might have written

if (value == 0)
    // do something

When value is changed from an int to a double, your safe integer comparison is now an unsafe floating point comparison that may produce unexpected results! In the best case, this error shows up when testing your program, and you have to spend time debugging it. In the worst case, the bug ships out and you end up with millions of customers have software that doesn’t work right!

However, if you’d used Hungarian Notation and written:

if (nValue == 0)
    // do something

And were forced to change it to:

if (dValue == 0.0)
    // do something

Hopefully at this point you’d say, “Hey, wait a second, I shouldn’t be doing naked comparisons with floating point values!”. Then you could modify it to something more appropriate and move on. In the long run, this can actually save you lots of time.

A real disadvantage of traditional Hungarian Notation is that the number of prefixes for compound types can become confusing. Wikipedia provides an appropriate example: “a_crszkvc30LastNameCol : a constant reference function argument, holding contents of a database column of type varchar(30) called LastName that was part of the table’s primary key”. a_crszkvc is non-trivial to decipher, and makes your code less clear.

As an aside, Hungarian Notation got it’s name from prefixes such as a_crszkvc that look like they’re written in Hungarian!

Caste Hungarian

Different programmers and/or companies tend to use different varieties of Systems Hungarian of varying complexity. Although most of them have some commonality (like using a d prefix for double, and an n (or i) prefix for integers), there is a lot of variation as to which types get what prefixes, and how those prefixes should combine.

We believe that using a different prefix for each data type is overkill, especially in the case of structs and classes, which can be user defined to a high degree. Furthermore, long Hungarian looking prefixes obscure code clarity more than they help it. Consequently we advocate a simplified version of Systems Hungarian called “Caste Hungarian”. In Caste Hungarian, Hungarian Notation is used mostly to denote which “caste” of data type a variable falls into (integers, floating points, classes, etc…).

Variable prefixes are composed of 3 parts: a scope modifier, a type modifier, and a type prefix (in that order). Scope modifier and type modifier may not apply. Consequently, the overall prefix length is kept reasonable, with the average prefix length being around 2 letters. This system conveys most of the advantages of Hungarian Notation without many of it’s disadvantages, and it keeps the entire system simple and easy to use.

The type prefix indicates the data type of the variable.

Type prefix Meaning Example
b boolean bool bHasEffect;
c (or none*) class Creature cMonster;
ch char (used as a char) char chLetterGrade;
d double, long double double dPi;
e enum Color eColor;
f float float fPercent;
n short, int, long
char used as an integer
int nValue;
s struct Rectangle sRect;
str C++ string std::string strName;
sz Null-terminated string char szName[20];

The following type modifiers are placed before the prefix if they apply:

Type modifier Meaning Example
a array on stack int anValue[10];
p pointer int* pnValue;
pa dynamic array int* panValue = new int[10];
r reference int rnValue;
u unsigned unsigned int unValue;

The following scope modifiers are placed before the type modifier if they apply:

Scope modifier Meaning Example
g_ global variable int g_nGlobalValue;
m_ member of class int m_nMemberValue;
s_ static member of class int s_nValue;

A few notes:

  1. This list is not exhaustive. It is meant to cover the most common cases. If you feel a variable of a different type deserves it’s own prefix, give it one!
  2. Use meaningful variable names and suffixes to clarify your variables. This is especially important with struct and class variables. For example, a Rectangle struct variable holding the position and size of a window is better declared as Rectangle sWindowRect; than Rectangle sWindow;
  3. Char has a different prefix depending on whether it’s being used as an ASCII character or integer. This helps clarify it’s intended use and prevent mistakes.
  4. Float has a different prefix than double because floating point literals are doubles by default. Float literals need a f suffix.
  5. Typedefs don’t fall very well into this system.
  6. The ‘c’ prefix for a class can be omitted if the variable is a pointer or a reference to a class.
  7. Because integer types are not differentiated, you can easily change to a larger or smaller integer as needed without changing the variable name. However, changing to a smaller integer is generally not recommended due to potential overflow issues.

Here are a few sample declarations:

int nIndex; // simple integer type prefix
int* pnIndex;  // a pointer to an integer
int m_nIndex; // an integer variable that is a member of a class
int* m_pnIndex; // an pointer to an integer variable that is a member of a class
2.10 — Comprehensive quiz
Index
2.8 — Constants

23 comments to 2.9 — Hungarian Notation

  • Adry

    My fav article on Hugarian notation: right here.

    It’s a bit long – winded, but really clears the whole thing out.

    • That’s a good article. There are a lot of different viewpoints on Hungarian Notation, whether it’s useful or not, and how it should be applied. There’s no “best answer” on this one. It’s largely up to each individual programmer (and/or the company they work for) to decide which way they would like to proceed.

  • [...] 2007 Prev/Next Posts « 2.9 — Hungarian Notation | Home | Three questions that need to be answered before you start writing your game » [...]

  • [...] 2007 Prev/Next Posts « 2.7 — Chars | Home | 2.9 — Hungarian Notation » Saturday, June 9th, 2007 at 10:43 [...]

  • Attila

    Well, I AM Hungarian, and have only 1 note on Hun.Not. You wrote, it looks like it was written in Hungarian. The truth is, real Hungarian is MUCH more difficult to decipher, than e.g. “a_crszkvc”… ;P

  • Jeffey

    I would like to add that even if you do end up having to change a variable name. It can easily be done by doing a Find and Replace search. Assuming you code correctly. There should be minimal risk doing it this way.

  • Another Attila

    I am also Hungarian. I have 20+ years of programming experience behind me, with various languages and projects scaling from one-man-show to large industrial applications; device drivers, embedded systems, GUI business apps etc. My comments are based on those experiences. Few comment of mine:

    Hungarian notation is a Fortran programmer’s desperate attempt to cope with not understanding C.

    I wish people would stop calling it Hungarian notation. Why? The person who made it left Hungary at an early age. The notation was made at/by Microsoft for Windows programming in C. In other words: it has nothing to do with Hungary or Hungarians in general. But (because in most cases it does damage where it is applied, and because it tends to make programs unreadable) now people are talking about “Hungarian warthogs”. Which in turn makes people think about warthogs when they hear the word Hungarian or Hungary. I am not kidding. It is from experience.

    Proof is that Hungarian notation is not Hungarian: The szar prefix is used in encoding certain types, IIRC it is string that is a zero terminated array or something like that. Szar means crap/shit in Hungarian. Not a word a Hungarian would use to describe his variables.

    In C++, the notation is mostly damaging. There is no empirical (or other) evidence that well designed C++ programs will benefit from it. But there is empirical evidence that it causes damage. Just look at wParam and the like in Windows API. It is not a word. It was, once, in 16bit days. The notation forces you to change your names (i.e.: interfaces) when you change a type, even if the type you use is compatible with the original, or a natural (pure) extension of it. Which in turn means that people will NOT change the name of the variables and so the prefix will lie.

    But the most important argument/point to understand why this notation is damaging is the following: The “type encoding variable name prefix” (I do not want to call it Hungarian notation) is DUPLICATING CODE. You have already told the type once! In the declaration. Putting it into the name of the type will result in serious duplication of code, which in turn is a serious violation of the once-and-only-once principle. Yes, I know the excuse: Your editor can change the variable names very fast. The problem with that excuse is that it is NOT TRUE, or if it is, it removes all the benefits of the type prefix. See my debunking of that theory below:

    You editor can find the occurrences of the particular variable name you want to change. Yes, it can find them very very fast. It can also replace them very very fast.

    1.) But if you replace them automatically, where is the benefit? Unless you look at each and every occurrence yourself, checking if it needs a change, how did you benefit from the type prefix? You did not. It only added more work. You can look at the occurrences of the name without changing the name to another! It it about the same amount of work in editing, but editing is not the only work you need to do when you change a file:

    2.) Changing a file will require that it is updated in a central repository or version control system. Let’s suppose that one update (checkout/checkin) takes only 2 seconds. (In real life it is a lot more.) That is 2 seconds time you have lost for each file that you have actually changed. If you do not need to change the variable name, only the infrequent lines where a real update is needed, you will perhaps check in one to 10 files. If you must change every use of the name, you will check in 100+ files. 20 seconds versus 200+ seconds. Changed files may need merging to other branches etc. You have complicated your life for future work as well.

    3.) Every changed file has to be re-tested. Regression. Depends on the length of the test runs, but we normally talk about days of additional work for nothing, because there was no real change to the majority of the code.

    I could continue to rant on. :) But let’s just say that Hungarian Notation in type safe languages is one of those ideas that appeal to the inexperienced, uneducated masses of casual or beginner programmers, but makes any experienced professional scream with horror.

    • bla

      But doesn’t the caste system avoid most of those disadvantages? I mean for example: you probably wouldn’t change an int to a floating point variable too often right? Also who would change a pointer to something else…

  • Julian

    “Though you fill find plently of programmers who disagree” I disagree with that sentence :P (fill = will?)

    [ Yup, typo. :) Thanks for letting me know. -Alex ]

  • Dave West

    I was always told that Hungarian notation was called that because it was invented by a Hungarian…

  • BorisTheSpider

    It’s apparently a hot issue, that Hungarian Notation. When the time comes, I suppose I’ll have to make the decision to use it or not, or how extensively. Regardless I really appreciate your explanation, so that I can make an educated decision when that time arrives.

  • Tom

    Hungarian Notation was invented in 1972 by Charles Simonyi, a Microsoft programmer.

    Maybe Hungarian Notation was invented in 1972, but Microsoft wasn’t founded until 1975.

    Charles Simonyi worked at Xerox PARC in 1972. He began his career at Microsoft in 1981.

  • Insert Name Here

    Typo: “…without many of it’s disadvantages.”
    But this is a great website.

  • Please people, don’t use Hungarian notation for obvious things like int nSomething. This is a result of misinterpretation of original purpose of Hungarian notation, and is annoying, confusing and stupid.

  • personguy

    you’re (not your) doing a great job, but, since we are being quite technical, it may, in reference to various sentences in this great tutorial, be worth pointing out: its. its. its. its.
    as long as we’re learning a new language we might as well keep the one it’s being taught in intact :)
    thx for all the great info and help!

  • Arthur944

    a_crszkvc doeasnt look like its been written in hungarian. If it does in some way, please explain it to me. (I am Hungarian.)

  • JohnM

    OK. I have to ask. Why n for integer instead of i??

You must be logged in to post a comment.