The Hungary markup method adds a prefix to the variable type or scope before the variable name.
1: int value; // non-Hungarian
2: int nValue; // the n prefix denotes an integer
3: double width; // non-Hungarian
4: double dWidth; // the d prefix denotes a double
There is a lot of controversy about the usefulness of Hungary markup in modern programming languages and modern IEDs. We believe that it is still more than its disadvantages, even though we can find many objections.
One advantage is that the Hungary tag can know the type of the variable through the variable name. Many people admit that this is an obsolete advantage, because now many ides place the mouse over the variable name to know the type of the variable. But let's look at the following code:
1: float applesPerPerson = totalApples / totalPersons;
This statement may not attract your attention. However, this may cause errors. If totalApples and totalPersons are both integer, the compiler will use integer division in totalApples/totalPersons calculation, resulting in loss of fractional parts. For example, if totalApples = 5 and totalPersons = 3, the result of applesPerPerson is 1 instead of 1.66!
If the Hungarian markup is used
1: float fApplesPerPerson = nTotalApples / nTotalPersons;
From the prompt of the n prefix, we can see that this statement has problems. In addition, the n prefix can also remind you of integer division and overflow problems.
Another advantage of the Hungarian naming method is that it allows us to name using abbreviations. For example, bError can be interpreted as isError, and nApples can be interpreted as numberOfApples.
A common problem with the Hungary markup method is the extra work caused by changing the type of a variable. For example, if you want to process the decimal part, you want to change an integer variable to a double variable. If you do not use the Hungary markup, you only need to change int to double. However, if you use the Hungarian notation, you cannot simply change int to double, you have to change the nValue to dValue! If your name is not changed in time, it will mislead you.
Although it is annoying to change a large number of variable names, we believe it is still good. Because different types have different behaviors, you can check your code by changing the variable name to ensure that there is no discomfort in the new type.
For example, do not use the Hungary markup:
1: if (value == 0)
2: // do something
When a variable is changed to double, your comparison will be insecure. When a problem occurs, you have to spend time debugging. If this bug is ignored, more problems may occur.
However, if you use the Hungarian markup:
1: if (nValue == 0)
2: // do something
1: if (dValue == 0.0)
2: // do something
When you see this, you may say "Hey, wait a second, I shouldn't be doing naked comparisons with floating point values !". Then you will make some corrections before continuing to execute
(Note: If the two floating point types are equal, it is better to use the difference between the two in a range as equal?
1: const double maxLow = 1e-10;
2: // use [fabs(dValue) < maxLow] instead of [dValue == 0.0]
3: if (fabs(dValue) < maxLow)
4: // do something
)
Traditionally, the disadvantage of the Hungarian labeling method is that the number of prefixes of the combination type may be confusing. wikipedia provides an 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 ". this makes your code hard to understand.
Caste Hungarian
Different groups use different Hungary naming systems. Although some things are the same, there are many differences.
We use different prefixes for each data type as overkill, especially for struct and class. Moreover, long Hungary naming is counterproductive. Therefore, we advocate the use of a simple Hungary naming system called caste Hungarian.
The prefix of a variable consists of three parts: range modification, type modification, and type prefix. The first two parts may not apply. Therefore, the length of all prefixes is reasonable, and the average prefix length is about 2 characters. This system includes many advantages of the Hungarian labeling method, and many shortcomings are arranged, making the entire system simple and easy.
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; |
Note:
1. These distances are not detailed. They include most cases. If you think that variables of different types deserve their own prefix, assign one
2. Use variable names with specific meanings to separate them. This is particularly important in struct and class. For example, Rectangle sWindowRect is much better than Rectangle sWindow.
3. When char is used as an ASCII character or integer, it has different prefixes and can be used to distinguish its purpose.
4. float and double have different prefixes.
5. typedefs is not suitable for this system
6. When a variable is a class reference or pointer, 'C' is disabled.
7. Because integer variables are not well differentiated, you can easily change a large integer variable to a small variable type without changing the name. However, this may cause overflow.
1: int nIndex; // simple integer type prefix
2: int* pnIndex; // a pointer to an integer
3: int m_nIndex; // an integer variable that is a member of a class
4: int* m_pnIndex; // an pointer to an integer variable that is a member of a class
The Hungary markup method adds a prefix to the variable type or scope before the variable name.
1: int value; // non-Hungarian
2: int nValue; // the n prefix denotes an integer
3: double width; // non-Hungarian
4: double dWidth; // the d prefix denotes a double
There is a lot of controversy about the usefulness of Hungary markup in modern programming languages and modern IEDs. We believe that it is still more than its disadvantages, even though we can find many objections.
One advantage is that the Hungary tag can know the type of the variable through the variable name. Many people admit that this is an obsolete advantage, because now many ides place the mouse over the variable name to know the type of the variable. But let's look at the following code:
1: float applesPerPerson = totalApples / totalPersons;
This statement may not attract your attention. However, this may cause errors. If totalApples and totalPersons are both integer, the compiler will use integer division in totalApples/totalPersons calculation, resulting in loss of fractional parts. For example, if totalApples = 5 and totalPersons = 3, the result of applesPerPerson is 1 instead of 1.66!
If the Hungarian markup is used
1: float fApplesPerPerson = nTotalApples / nTotalPersons;
From the prompt of the n prefix, we can see that this statement has problems. In addition, the n prefix can also remind you of integer division and overflow problems.
Another advantage of the Hungarian naming method is that it allows us to name using abbreviations. For example, bError can be interpreted as isError, and nApples can be interpreted as numberOfApples.
A common problem with the Hungary markup method is the extra work caused by changing the type of a variable. For example, if you want to process the decimal part, you want to change an integer variable to a double variable. If you do not use the Hungary markup, you only need to change int to double. However, if you use the Hungarian notation, you cannot simply change int to double, you have to change the nValue to dValue! If your name is not changed in time, it will mislead you.
Although it is annoying to change a large number of variable names, we believe it is still good. Because different types have different behaviors, you can check your code by changing the variable name to ensure that there is no discomfort in the new type.
For example, do not use the Hungary markup:
1: if (value == 0)
2: // do something
When a variable is changed to double, your comparison will be insecure. When a problem occurs, you have to spend time debugging. If this bug is ignored, more problems may occur.
However, if you use the Hungarian markup:
1: if (nValue == 0)
2: // do something
1: if (dValue == 0.0)
2: // do something
When you see this, you may say "Hey, wait a second, I shouldn't be doing naked comparisons with floating point values !". Then you will make some corrections before continuing to execute
(Note: If the two floating point types are equal, it is better to use the difference between the two in a range as equal?
1: const double maxLow = 1e-10;
2: // use [fabs(dValue) < maxLow] instead of [dValue == 0.0]
3: if (fabs(dValue) < maxLow)
4: // do something
)
Traditionally, the disadvantage of the Hungarian labeling method is that the number of prefixes of the combination type may be confusing. wikipedia provides an 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 ". this makes your code hard to understand.
Caste Hungarian
Different groups use different Hungary naming systems. Although some things are the same, there are many differences.
We use different prefixes for each data type as overkill, especially for struct and class. Moreover, long Hungary naming is counterproductive. Therefore, we advocate the use of a simple Hungary naming system called caste Hungarian.
The prefix of a variable consists of three parts: range modification, type modification, and type prefix. The first two parts may not apply. Therefore, the length of all prefixes is reasonable, and the average prefix length is about 2 characters. This system includes many advantages of the Hungarian labeling method, and many shortcomings are arranged, making the entire system simple and easy.
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; |
Note:
1. These distances are not detailed. They include most cases. If you think that variables of different types deserve their own prefix, assign one
2. Use variable names with specific meanings to separate them. This is particularly important in struct and class. For example, Rectangle sWindowRect is much better than Rectangle sWindow.
3. When char is used as an ASCII character or integer, it has different prefixes and can be used to distinguish its purpose.
4. float and double have different prefixes.
5. typedefs is not suitable for this system
6. When a variable is a class reference or pointer, 'C' is disabled.
7. Because integer variables are not well differentiated, you can easily change a large integer variable to a small variable type without changing the name. However, this may cause overflow.
1: int nIndex; // simple integer type prefix
2: int* pnIndex; // a pointer to an integer
3: int m_nIndex; // an integer variable that is a member of a class
4: int* m_pnIndex; // an pointer to an integer variable that is a member of a class