...
Wiki Markup |
---|
When used in program logic, literals can reduce the readability of source code. As a result, literals in general, and integer constants in particular, are frequently referred to as _magic numbers_ because their purpose is often obscured. Magic numbers aremay be constant values that represent either an arbitrary value (such as a determined appropriate buffer size) or a malleable concept (such as the age a person is considered an adult, which could change between geopolitical boundaries). Rather than embed literals in program logic, use appropriately named symbolic constants to clarify the intent of the code. In addition, if a specific value needs to be changed, reassigning a symbolic constant once is more efficient and less error prone than replacing every instance of the value. \[[Saks 02|AA. C References#Saks 02]\]. |
...
Method | Evaluated at | Consumes Memory | Viewable by Debuggers | Type Checking | Compile-time constant expression |
---|---|---|---|---|---|
Enumerations | compile time | no | yes | yes | no yes |
| run time | yes | yes | yes | no |
Macros | preprocessor | no | no | no | yes |
...
Wiki Markup |
---|
Using the {{sizeof}} expression in this example reduces the total number of names declared in the program, which is generally a good idea \[[Saks 02|AA. C References#Saks 02]\]. The {{sizeof}} operator is almost always evaluated at compile time (except in the case of variable length arrays). |
Non-Compliant Code Example
In this non-compliant code example, the string literal "localhost"
and integer constant 1234
are embedded directly in program logic, and are consequently difficult to change.
Compliant Solution
Code Block | ||
---|---|---|
| ||
if ( (ld = ldap_init("localhost", 1234)) == NULL) {
perror("ldap_init");
return(1);
}
|
Compliant Solution
In this compliant solution, the host name and port number are both defined as object-like macros, so that Constant values that may be passed as compile-time arguments must be macro definitions, as shown by this example:.
Code Block | ||
---|---|---|
| ||
#ifndef PORTNUMBER /* might be passed on compile line */ # define PORTNUMBER 1234 #endif #ifndef MYPORTNUMBERHOSTNAME /* might be passed on compile line */ # define MYPORTNUMBERHOSTNAME 1234 #endif"localhost" #endif /* ... */ if ( (ld = ldap_init(HOSTNAME, PORTNUMBER )) == NULL) { perror("ldap_init"); return(1); } |
Exceptions
DCL06-EX1: While replacing numeric constants with a symbolic constant is often a good practice, it can be taken too far. Remember that the goal is to improve readability. Exceptions can be made for constants that are themselves the abstraction you want to represent, as in this compliant solution.
...