Code Complete --- (Note3 Variables)

本文探讨了在软件开发中使用变量和数据类型的最佳实践,包括初始化策略、变量作用域、命名规范、基本数据类型的选择及注意事项等。通过遵循这些指导原则,可以提高代码质量并减少潜在错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Code Complete --- (Part3 Variables)

=========================================================
1. General issues in using variables

 A pompus[华而不实的] fraud [骗子] --- 绣花枕头

Following are guidelines for avoiding initialization problems,
---- Initialize each variable as it's declared
---- Initialize each variable close to where it's first used
---- Use const when possible
---- Pay speical attention to counters and accumulators, i, j, k, total
---- Initialize a class's member data in its constructor
---- Initialize working memory at the beginning of your program ,
     0xCC is a good value to use because it's the machine code for a breakpoint interrupt(int 03h).

Scope
---- Keep variable "Live" for as short a time as possible

Persistence

Binding Time  (In general, the later you make the binding time, the more flexibility you build into your code)
---- The earliest possible time at Code-Writing time
      Title.Color = 0xFF;
---- A slightly later time at Compile time
      const int TITLE_COLOR = 0xFF;
      Title.Color = TITLE_COLOR;
---- The later time at Run time
      Title.Color = ReadTitleColor();

Coding time (use of magic numbers)
Compile time (use of named constant)
Load time (reading a value from an external source such as Windows registry file)
Object instantiation time (reading value each time a window is created)
Just in time (reading value each time the window is drawn)

Using each variable for exactly one purpose
=========================================================
2. The power of variable names

Considering in choosing good names
---- Problem orientation, speak to the problem rather than the solution, express the 'what' more than 'how', refers to the problem domain rather than the computing universe.
---- Optium name length
---- the effect of scope on variable names, use qualifiers on names that are in the global namespace
---- computed-value qualifiers in variable names
     Many programs have variables that contain computed values: totals, averages, maximums, and so on. If you modify a name with a qualifier like Total, Sum, Average, Max, Min, Record, String, or Pointer, put the modifier at the end of the name.
---- Common Opposites in variable names

Naming special types of data
---- Naming Loop Indexes, i,j,k, or more informative name.
---- Naming Status Variables, think of a better name than 'flag' for status variable, 'printerReady'.... or enum type
---- Naming temporary variables
---- Naming Boolean variables
     Keep typical boolean names in mind
        ---- 'done', 'error','found', 'success','ok','ready'
      IsFound, if (IsFound) --- if (found) would be better
---- Naming Enumerated types
     C++ Color_Green, Color_Red....
     C#   Green, Red (Color.Green, Color.Red)...
---- Naming Constants , using named variable
 
The power of naming conventions
    There are no hard-and-fast rules[金科玉律] for when you should establish a naming convention, but here are a few cases in which conventions are worthwhile:
  ---- When multiple programmers are working on a project
  ---- When you plan to turn a program over to another programmer for modifications and maintenance (which is nearly always)
  ---- When your programs are reviewed by other programmers in your organization
  ---- When your program is so large that you can't hold the whole thing in your brain at once and must think about it in pieces
  ---- When the program will be long-lived enough that you might put it aside for a few weeks or months before working on it again
  ---- When you have a lot of unusual terms that are common on a project and want to have standard terms or abbreviations to use in coding

Guidelines for a language-independent convention
---- Differentiate between variable names and routine names, begin with lower case/upper case: myName, MyName();
---- Differentiate between classes and objects
---- Identify global variables, g_RunningTotal, names with g_ prefix
---- Identify member variables, m_
---- Identify type definition,  t_, t_char
---- Identify named consts, use all upper case letters, MAX
---- Identify elements of enumerated types, Color_
---- Identify input-only parameters in languages that don't enforce them, const &, *
---- Format names to enhance readability, Point_Total
....
C++ Constants, typedef, and preprocessor macros are in ALL_CAPS

=========================================================
3. Fundamental data types

Number in General
---- Avoid "magic numbers"
    use hard-code 0 and 1 if you need to
---- Anticipate divide-by-zero errors
---- Make type conversions obvious
---- Avoid mixed-type comparsions
---- Heed your compiler's warnings

Integers[5intidVE]
---- Check for integer division   7/10 != 0.7, so 10 *(7/10) != 7 *******
---- check for integer overflow
---- Check for overflow in intermediate results

Float-point numbers
---- Avoid additions and subtractions on numbers that have greatly different magnitudes
      1,000,000.00 + 0.1 probably produces an answer of 1,000,000.00
---- Avoid equality comparisons
     const double ACCEPT_DELTA = 0.00001;
     bool Equals(double termSource, double termTarget){
            if (Math.abs(termSource - termTarget) < ACCEPT_DELTA )
                return true;
            else
                return false;
     }
   ---- Anticipate rounding errors   (you multiply dollars by 100 ....)

Characters and Strings
---- Avoid magic charactes and strings
---- Strings in C
     ---- Be aware of the difference between string pointers and character arrays
        StringPtr = "Some Text String";
        In this case, "Some Text String" is a pointer to a literal text string and the assignment merely sets the pointer StringPtr to point to the text string. The assignment does not copy the contents to StringPtr.
     ---- Declare C-Style strings to have length CONSTANT + 1
            char name[ NAME_LENGTH + 1 ] = { 0 };
            for ( i = 0; i < NAME_LENGTH; i++ )   
                   name[ i ] = 'A';
     ---- Intialize strings to null to avoid endless strings.
            You can avoid endless strings in two ways. First, initialize arrays of characters to 0 when you declare them ---- char EventName[ MAX_NAME_LENGTH + 1 ] = { 0 };
            Second, when you allocate strings dynamically, initialize them to 0 by using calloc() instead of malloc(). calloc() allocates memory and initializes it to 0. malloc() allocates memory without initializing it, so you take your chances when you use memory allocated by malloc().
     ---- Use arrays of characters instead of pointers in C
     ---- Use strncpy() instead of strcpy() to avoid endless strings.
            strcpy() and strcmp() keep going until they run into a null terminator. Their safer companions, strncpy() and strncmp(), take a parameter for maximum length so that even if the strings go on forever, your function calls won't.

Boolean variables
---- Use boolean variables to simplify complicated tests to document your program
     if ( ( elementIndex < 0 ) || ( MAX_ELEMENTS < elementIndex ) ||
       ( elementIndex == lastElementIndex )
       ) {
           ...
          }

      finished = ( ( elementIndex < 0 ) || ( MAX_ELEMENTS < elementIndex ) );
      repeatedEntry = (elementIndex == lastElementIndex );
      if ( finished || repeatedEntry ) {
          ...
      }

Named Constants
---- Use named constants in data declarations
---- Avoid literals, even 'safe' ones
     For i = 1 To 12
     For month = Month_January To Month_December

Arrays
---- In C, use the ARRAY_LENGTH(x) macro to work with arrays
     #define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))

Creating your own types (type aliasing)
    typedef float Coordinate;

---- Avoid predefined types
---- Don't redefine a predefined type
---- Define substitue types for portability
     define a type INT32 and use it instead of int, or a type LONG64 instead of long
---- Consider creating a class rather than using a typedef
=========================================================
4. Unusual data types

Structures
---- use structures to clarify data relationships
---- use structures to simplify operations on blocks of data
---- use structures to simplify parameter lists
---- use structures to reduce maintenance

Pointers
The knowledge of how to interpret the contents of a location in memory is provided by the base type of the pointer. If a pointer points to an integer, what that really means is that the compiler interprets the memory location given by the pointer as an integer.

General tips on pointers
---- lsolate pointer operations in routines or classes
---- Declare and define pointers at the same time
---- Delete pointers at the same scoping level as they were allocated
---- Check pointers before using them
---- Check the variable reference by the pointer before using it
---- Usd dog-tag fields to check for corrupted memory
---- Use extra pointer variable for clarity to simplify complicated pointer expressions
        startNode->next->previous
        Node *followingNode = startNode->next
---- Shred your garbage/Set pointers to null after deleting or freeing them/Check for bad pointers before deleting a variable
        ASSERT(pointer != NULL, "Attempting to delete null pointer.");
        memset(pointer, GARBAGE_DATA, MemoryBlockSize(pointer));
        delete pointer;
        pointer = NULL;
---- Keep track of pointer allocations
        IsPointerInList(pointer)

---- Write cover routines to centralize your strategy to avoiding pointer problems
    
#define  SAFE_DELETE(pointer) { 
        ASSERT(pointer 
!=  NULL,  " Attempting to delete null pointer. " ); 
        
if  (IsPointerInList(pointer)) 
            memset(pointer, GARBAGE_DATA, MemoryBlockSize(pointer)); 
            delete pointer; 
            pointer 
= NULL; 
        }
 
        
else  
            ASSERT(FALSE,
"Attempting to delete unallocated pointer."); 
        }

    }


C++ pointers
---- Understand the difference between pointers and references
    The most significant differences are that a reference must always refer to an object, whereas a pointer can point to null, and what a reference refers to can't be changed after the reference is initialized.
---- Use pointers for "pass by reference" parameters and use const references for "pass by value" parameters

Global Data
Using Access Routines Instead of Global Data
---- You get centralized control over the data.
---- You can ensure that all references to the variable are barricaded.
---- You get the general benefits of information hiding automatically.
---- Access routines are easy to convert to an abstract data type.

How to  Use Access Routines
Hide data in a class. Declare that data by using the static keyword or its equivalent to ensure only a single instance of the data exists. Write routines that let you look at the data and change it. Require code outside the class to use the access routines rather than working directly with the data.
if you have a global status variable g_globalStatus that describes your program's overall status, you can create two access routines: globalStatus.Get() and globalStatus.Set()
---- Require all code to go through the access routines for the data
---- Don't just throw all your global data into the same barrel
---- Build a level of abstraction into your access routines
---- Keep all accesses to the data at the same level of abstraction
     node = node.next        account = NextAccount( account )
                                            employee = NextEmployee( employee )

    event = EventQueue[ queueFront ]      event = HighestPriorityEvent()
    event = EventQueue[ queueBack ]       event = LowestPriorityEvent()
    eventCount = eventCount - 1                 RemoveEvent( event )
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值