Programming
----
What is a good programmer? Is it a lot of technical details? Or do you understand the underlying programming? Or is the programming speed is faster? I don't think it is. For some technical details and the underlying technology, as long as you see help, check the information can be found. For speed fast, as long as you make more, you will be able to happen.
I think a good programmer should have the following qualities:
1. There is a special spirit, diligent good, and one anticipate. 2, positive attitude, creative thinking. 3. The ability to actively communicate with people, there is team spirit. 4, modesty and cautious, arrogance and arrogance. 5, the code written is high. Including: Code stability, easy reading, standardization, easy maintenance, professional.
These are the cultivation of programmers. Here I want to talk about "programming cultivation", which is the 5th point in the above. I think, if I want to know a author, I will see what he wrote. If I want to know a painter, I will see the drawing he draws. If I want to know a worker, I will see what he makes it. Similarly, if I want to understand a programmer, I want to first think that his program code, the program code can see a programmer's quality and cultivation, the program is like a work, qualified procedures The work must be a beautiful picture, a wonderful song, a pleasing novel.
I have seen many programs, there is no comment, there is no narrow, the name of the variable name, etc., wait, I will collect this person as there is no cultivation, this programmer is doing creative work? No, it is completely destroyed. They are said to be programs, but it is better to "encrypt" on the source program. This kind of programmer should be expelled, because he edited the value, It is far less than the value that needs to be maintained above.
Programmers should have programmers, so afraid of tired, no time, but also to be responsible for their own procedures. I would rather want the programmer that is slow, technical, but there is a good writing program style, or the programmer of "destroying" skills. There is a saying that "the word is like a person", I want to see a programmer from the program. Because the program is a programmer's work, the quality of the work is related to the reputation and quality of the programmer. The "cultivation" good programmer must make good procedures and software.
There is a idiom called "alone", meaning what you have to do very professional, very careful, if you have to be a "craft", it is a deep person, then, from a very simple work. It seems that you have the characteristics of "craftsman", I think it is not difficult to do a programmer, but it is not easy to do a "programmer". The programming is very simple, but it is difficult to compose quality procedures.
I don't discuss excessive technology here, I just want to say something that is easy to ignore, although these things may be fine, if you don't pay attention to these subtle, then he will be very big. The impact of your entire software quality, as well as the implementation of the entire software, the so-called "Thousand Miles of Bius, Destroyed in Ant Accent".
"Seeing the truth in the wealth", I can really embody the bottom of a program is just in these subtle.
This is the programmer - programming cultivation. I summed up 32 "cultivation" on the program writing with C / C language (mainly C language). Through these, you can write a high quality program, and you will also let the human stains you have Stains, those who have seen your procedure will definitely say: "This person's programming is not bad."
------------------------ 01, copyright and version 02, indentation, space, wrap, blank line, align 03, program notes 04, functions [In] [OUT] Parameters 05, the return of the system call is determined 06, if statement pairs the error 07, the #ifndef 08 in the header file, allocates the memory 09 on the heap, the initialization of the variable 10, H, and C files Use 11, error information 12, common function, and naming number of named 14, function name, and variable name in the circulatory statement, the pass value of the variable name, the passage of the function, and modify the cultivation of the person program 16, put the same or near The same code forms function and macro 17, brackets in the expression, the number of Const 19 in the function parameters, the number of parameters of the function 20, the return type of the function, do not omit 21, the use of the GOTO statement 22, macro use 23, Static Use the code size 25 in the function, the use of TypeDef 26, for the constant declaration macro 27, do not perform order 29, ||, and &&'s statement to execute the order 29, try to use for for why , Please sizeof type instead of the variable 31, don't ignore Warning 32, writing Debug and Release version of the program 1, copyright and version
-------
Good programmers will pay a copyright and version of each file, each file.
For C / C files, the file head should have a comment like this: / ******************************** **************************************** File name: network name: network.c ** file Description: Network Communication Function Set ** Creation: Hao Chen, February 3, 2003 ** Version Number: 1.0 ** Modify Record: ****************** *********************************************************** **** /
For functions, there should also be similar to this note:
/ * ================================================================================================================================================================ ================== * * Function name: xxx * * parameter: * * Type name [in]: descripts * * Function Description: * * ....... ....... * * Return Value: Success True, failed false * * throw exception: * * Servers: chenhao 2003/4/2 * =============== ========================================================= * / Such a description allows people to have a function, a file has a general understanding, which has a great advantage to the easy-to-readability and easy maintenance of the code. This is a good start.
2, indent, space, wrap, blank line, alignment -------------- i) indentation should be done every program, as long as the program is programs, you should know This, but I still have seen the procedure that does not indent, or the procedure that is indent, if your company also has a programmer who writes the program, please open him without hesitation, and destroys the sin of the source Prosecution of him, but he still compensates that the mental loss fees for those who have read his procedures. Indent, this is an incumbent rule, and I will retrieve it, a indentation is generally a Tab key or 4 spaces. (It is best to use Tab keys)
II) space. Does the space will give the program? No, effective use of spaces can make your program read more and pleasing. Not a pile of expressions are squeezed together. Take a look at the code below:
HA = (HA * 128 * Key )% tabptr-> size;
HA = (HA * 128 * Key )% tabptr-> size;
It feels different from space and no space. In general, the statement is equipped between the individual operations, and when the function is called, it is equipped with each parameter. Such a split and non-added: IF ((HPROC = OpenProcess, false, pid) == null) {}
IF ((HPROC = OpenProcess, false, pid) == null) {}
Iii) Retained. Don't write the statement on a line, this is very bad. Such as:
For (i = 0; i
CreateProcess (NULL, CMDBUF, NULL, NULL, BINHH, DWCRTFLAGS, ENVBUF, NULL, & SistartInfo, & Prinfo);
Conditional statements should also be wrapped when necessary: if (CH> = '0' || CH <= '9' || CH> = 'A' || CH <= 'Z' || CH> = 'A' | | CH <= 'Z')
IV) blank line. Don't spoil, the blank line can distinguish between different blocks, blocks, and best to add space lines. Such as:
Handle HProcess; Process_t procinfo;
/ * Open the process Handle * / IF (HProcess = OpenProcess, false, pid) == null) {RETURN LSE_MISC_SYS;}
Memset (& Procinfo, 0, Sizeof (procinfo); procinfo.idproc = pid; procinfo.hdproc = hprocess; procinfo.misc | = mscava_proc;
Return (0); V) is aligned. Use the Tab keys to the declaration or comment of your variables, you will make your program look good. Such as:
typedef struct _pt_man_t_ {int numProc; / * Number of processes * / int maxProc; / * Max Number of processes * / int numEvnt; / * Number of events * / int maxEvnt; / * Max Number of events * / HANDLE * pHndEvnt; / * Array Of Events * / DWORD TIMEOUT; / * TIME OUT Interval * / Handle Hpipe; / * namedpipe * / tchar USR [MAXUSR]; / * user name of the process * / int Nummsg; / * Number of message * / INT msg [maxmsg]; / * Space for intro process communicate * /} Pt_man_t; how? It feels good.
Here mainly tells the story, if you write a pleasing code, the good-looking code will make people feel happy, read the code, not tired, work, neat program code, usually more welcome, more people. Now the hard disk space is so big, don't let your code squeeze together so they will complain that you abuse them. Ok, use "indentation, space, wrap, blank, align" to decorate your code, let them get a row of ordinary organs from there is no order.
3, program comments ------ Develop the habit of writing the program annotation, this is the work that each programmer must do. I have seen that thousands of lines, but there is no row of comments. This is like driving on the road, but there is no road sign. How long does it take? I don't know my intention, I have to spend a few times, I understand that this kind of people who waste others and their own time are the most compussia.
Yes, you may say, you will write a comment, really? The writing of the comment can also see a programmer's skill. Generally speaking, you need to write a note at least in these places: The annotation of the file, the comment of the function, the comment of the variable, the comment of the algorithm, the program comment of the function block. Mainly to record what is your program? What is your intent? What is your variable used? and many more.
Don't think about it, there are some algorithms that it is difficult or written. It can only be aimed. I admit that there is this situation, but you have to write it, just can train your own expression. The ability to express the technicians of the kind of technicians who are stuffy, you have a high technology, if you express your ability, your technology will not be able to get full. Because this is a team's era.
Ok, say the technical details of a few comments:
i) I don't agree with the row bet ("//") than the block annotation ("/ * * /"). Because some old versions of the C compiler do not support row notes, for your program's portability, please try to use block comments.
II) You may not be nested by the block annotation, then you can use the precompilation to complete this feature. Use the code enclosed in "#IF 0" and "#ndif", will not be compiled, and it can be nested. 4, function [in] [out] parameter -----------
I often see such procedures: funcname (char * str) {int Len = strlen (str); .....}
Char * getUsername (Struct User * Puse) {Return PUSER-> Name;}
Do not! Please don't do this.
You should first judge that the pointer to come in is empty. If the pointer passed is empty, then a big system will crash because of this small function. A better technology is to use assertions (Assert), here I don't have much to say these technical details. Of course, if it is in C , reference is much better than the pointer, but you also need to check each parameter.
When writing a function of parameters, the primary work is to perform all the parameters that come in and perform legality checks. The parameters of the outgoing parameters should also be checked. This action should of course be external to the function, that is, after the call is completed, the value it will be checked.
Of course, check will be wasted, but for the entire system, "illegal operation" or "Core Dump" error, how many spends this time is still worth it.
5, the return to the system call to determine -------------- Continue the previous one, for some system calls, such as opening the file, I often see that many programmers return to FOPEN not Do any judgment, use it directly. Then find that the content of the file is not read, or you can't write it. Still judge:
FP = fopen ("log.txt", "a"); if (fp == null) {printf ("error: Open file error / n"); Return False;
There are still many other, such as: Socket number returned by Socket, Malloc returned by Mall. Please judge what these system calls returned. 6, if statement handles the error
-----------
I saw you said, what is good to say. Still first look at a program code.
IF (CH> = '0' && ch <= '9') {/ * Normal processing code * /} else {/ * Output error message * / printf ("error ... / n"); Return False;
This structure is very bad, especially if "normal processing code" is long, it is best not to use ELSE for this situation. Judgment the error first, such as:
IF (CH <'0' || CH> '9') {/ * Output Error message * / printf ("error ... / n"); return (false);} / * Normal processing code * / ...
Is this structure not very clear? Highlight the wrong condition, let others use your function, you can see unhanectation conditions, so you will be more conscious.
7, #ifndef in the header file ---------- Don't ignore the #ifndef in the first part, this is a very critical thing. For example, you have two C files, both C files include the same header file. When compiling, these two C files should be compiled into a run file, so there is a problem, a large number of statements conflicts. Still put the contents of the header files in #1ndef and #ndif. Whether your header will be referenced by multiple files, you have to add this. The general format is like this:
#ifndef
#ifndef _STDIO_H_ #define _stdio_h_ ... #ENDIF (BTW: More useful features for precompilation. Will you use pre-compiled?)
8, allocate memory on the pile --------- Many people may not understand the "stack stack" and "stack of HEAP" on memory allocation. People who include some barborses are not understanding these two concepts. I don't want to say more about these two things. Simply put, the memory system allocated on the Stack is automatically released, the memory allocated on the HEAP is not released, even if the program exits, the memory is still there. Stack is typically static allocation of memory, and HEAP is generally dynamically allocated.
The memory allocated by the Malloc system is allocated from the heap. The memory allocated from the pile must be released by himself. Use free release, or the term - "Memory Leak" (or "Memory Vulnerability") - Memory Leak. Thus, the system's allocated memory will be less and less Mallo, until the system crashes. Let's take a look at the difference between "stack memory" and "stack memory".
Stack memory allocation ----- char * allocstrfromstack () {char pstr [100]; return pstr;} 内 分 ----- char * allocstrfromheap (int LEN) {char * pstr; if (len <= 0 Return null; return (char *) malloc (len);
For the first function, the internal presence of the PSTR is released by the system when the function returns. So the return of the char * is nothing. For the second function, it is allocated from the heap, so even if the program is exited, it is not released, so the memory returned by the second function is no problem, which can be used. But must call free release, otherwise Memory Leak!
The distribution of memory is easy to cause memory leaks, which is the largest "gith" of C / C . If your program is stable, then Do not appear Memory Leak. So, I still have to pay a thousands of people here, be careful when using the Malloc system function (including Calloc, Realloc).
Remember to have a service application on UNIX, there are a few hundred C files compiled, run a good test, etc., the system is Down every three months, and many people can't find the problem. . I have to manually restart the system every two months. This problem is that MeMery Leak is strange, and this problem in C / C will always happen, so you must be careful. A Rational's Detection Work - Purify, you can help you test your programs do not have memory leaks. I promise that the programmer of many C / C projects will have some cold in Malloc or New. When you use Malloc and New, there is a light tight and fearful feeling, you have this kind of cultivation. For Malloc and Free operations have the following rules:
1) Pairing, there is a malloc, there should be a free. (C corresponds to new and delete) 2) Try to use on the same layer, do not like the above, Malloc in the function, and free outside the function. It is best to use these two functions on the same call layer. 3) Malloc allocated memory must initialize. The pointer behind free must be set to NULL.
Note: Although the current operating system (such as Unix and Win2K / NT) have process memory tracking mechanism, that is, if you have released memory, the operating system will help you release it. However, the operating system still does not release all the memory of Memory Leak in your program, so it is best to do this work. (Sometimes I don't know anything, there is a Memory Leak, and I find a non-sea cut pin in the code of millions of rows. Rational has a tool called Purify, which may be good to check the Memory Leak in the program.
9, the initialization of the variable -------- Joined the above, the variable must be initialized and reused. The C / C compiler will not help you initialize like Java, all need you, if you use no initialized variables, the result is unknown. Good programmers have never initialized the variables before using variables. Such as:
1) MEMSET cleared operations for Malloc allocation. (You can use the Calloc assigning a total memory) 2) Initialize the Struct or array assigned on some stacks. (It is best to clearly), but also said that it is back, initialization will also cause a certain overhead of the system running time, so don't initialize all variables, this is meaningless. A good programmer knows which variables need to be initialized, which is not required. Such as: The following situations are not required. Char * pstr; / * A string * / pstr = (char *) Malloc (50); if (pstr == null) exit (0); strcpy (pstr, "hello qld");
But if it is the case, it is best to perform memory initialization. (The pointer is a dangerous thing, must initialize)
Char ** pstr; / * A string array * / pstr = (char **) Malloc (50); if (pstr == null) exit (0); / * Make pointers in array points to null * / memset (PSTR, 0, 50 * SIZEOF (CHAR *)); for global variables, and static variables, it must be initialized when declaring. Because you don't know where it will be used for the first time. So the initial use before use is more unrealistic, so you must initialize them when declaring. Such as: links * plnk = null; / * For global variables PLNK initialized to null * /
10, how to use H and C files --------- H files and C files? In general, the H file is a Declare, which is define in the C file. Because the C file should be compiled into the library file (Windows is .Obj / .lib, UNIX is .o / .a), if others want to use your function, then reference your H file, so h file Generally, variables, macro definitions, enumeration, structures, and function interfaces, just like an interface description file. The C file is a detail.
The maximum use of H files and C files is declaration and implementation. This feature should be recognized, but I still see some people like to write the function in the H file, this habit is very bad. (If it is C , for its template function, only the implementation and declarations in the VC are written in a file because the VC does not support the export keyword). Moreover, if the implementation of the function is written in the H file, you have to add the dependency of the header file in makefile, which will make your makefile unregistered.
Finally, there is a place that is most important to pay attention to: the global variable with initialization should not be put in the H file!
For example, there is a structure that handles error messages:
Char * errmsg [] = {/ * 0 * / "no error", / * 1 * / "open file error", / * 2 * / "failed in sending / receiving a message", / * 3 * / "BAD Arguments ", / * 4 * /" Memeroy Is Not Enough ", / * 5 * /" Service is Down; Try Later ", / * 6 * /" Unknow Information ", / * 7 * /" a socket Operation Has Failed ", / * 8 * /" permission denied ", / * 9 * /" bad configuration file format ", / * 10 * /" communication time out ", ... ......}; Don't put this thing in the header file, because if your header is used by 5 function libraries (.lib or .a), he is linked in these 5 .lib or .a, and If your program uses a function in these five functions libraries, and these functions have been used in an array of error information. Then this information will have 5 copies existing in your executter. If your Errmsg is big, and your execution file will become bigger. The correct way to write it into the C file, and then add external declaration on each of the Errmsg's C file headers, let the compiler will take him when the compiler is in the link. Come, there will only be an errmsg exists in the execution file, and so that this is good to package.
The most crazy thing I have encountered is that in my target file, this errmsg has a total of 112 copies, and the execution file is about 8m. When I put errmsg in the C file, and after more than a thousand C files with Extern declaration, all the function library files decreased by about 20%, and my executive file was only 5m. There is a little less than 3m.
[Note] ----- There is a friend to tell me, this is just a special case, because if errmsg exists in the execution file, speed up the program running speed, the reason is that the multiple copies of errmsg will make the system The memory change is reduced and the efficiency is improved. There is only one errmsg we mentioned here. When a function is to use Errmsg, if the memory is far apart, it will generate a change, but the efficiency is not high.
This statement is not reasonable, but in general, for a relatively large system, errmsg is relatively large, so that the copy caused the size of the execution file to become large, not only adding the system loading time, but also a program in memory More page. For ERRMSG such data, in general, it will not be used frequently when the system is running, so the memory switching is not frequent. Under the trade-off, there is only one efficiency of Errmsg. Even if it is used frequently like LogMSG, the operating system's memory scheduled algorithm will allow such frequently used pages to be stored, so there will be no memory change issues. 11, the process of error information ---------
Will you handle error information? Oh, it is not a simple output. Look into the example below:
IF (p == null) {Printf ("Err: The Pointer Is Null / N);} Say goodbye to the programming of the student era. This programming is very disadvantageous for maintenance and management, error information, or prompt information, should be unified, not like the above, write into a "hard coded". Article 10 describes a part of this in this regard. If you want to manage the error message, you have the following processing:
/ * Declaration error code * / #define ERR_NO_ERROR 0 / * No error * / #define ERR_OPEN_FILE 1 / * Open file error * / #define ERR_SEND_MESG 2 / * sending a message error * / #define ERR_BAD_ARGS 3 / * Bad arguments * / #define ERR_MEM_NONE 4 / * Memeroy is not enough * / #define ERR_SERV_DOWN 5 / * Service down try later * / #define ERR_UNKNOW_INFO 6 / * Unknow information * / #define ERR_SOCKET_ERR 7 / * Socket operation failed * / #define ERR_PERMISSION 8 / * Permission denied * / #define err_bad_format 9 / * Bad configuration file * / #define err_time_out 10 / * Communication Time Out * / / * declaration error message * / char * errmsg [] = {/ * 0 * / "no error" , / * 1 * / "Open file error", / * 2 * / "failed in sending / receiving a message", / * 3 * / "bad arguments", / * 4 * / "memeroy IS not enough ", / * 5 * /" service is down; try latter ", / * 6 * /" unknow information ", / * 7 * /" a socket Operation Has Failed ", / * 8 * /" Permission Denied ", / * 9 * /" Bad Configuration File Format ", / * 10 * /" Communication Time Out ",}; / * Declaration Error Code Global Variable * / long errno = 0; / * Print error information function * / void PERROR (CHAR * INFO) {IF (info) {Printf ("% s:% s / n", info, errmsg [errno]); return;} printf ("error:% s / n", errmsg [errno] }
This is basically ansi error handling detail, so you can do this when you have an error in your program: BOOL Checkpermission (CHAR * UserName) {IF (Strcpy (UserName, "Root")! = 0) {Errno = Err_Permission_Denied; return (false);} ...} main () {... if (! Checkpermission ("") {PERROR ("main ()");} ...} A common, there is a personality Error message processing, doing advantageous as an error, unifying user interface, without failure, A programmer out, and a programmer has an information. And do this, it is very easy to maintain. The code is also easy to read.
Of course, the object must be reversed, nor is therefore necessary to put all the outputs in Errmsg, extracting more important error messages or prompting information is the key, but even though, this also includes most of the information.
12. Common functions and cyclic statements in the calculated quantity ---------------- Look at the following example:
For (i = 0; i <1000; i ) {getLocalHostName (HostName); ...} getLocalHostname means that it will get the current computer name, in the cyclic body, it will be called 1000 times. How much do this have no efficiency. This function should be taken to the cyclic body, which is only called once, and the efficiency has been greatly improved. Although our compiler will optimize, we will get the unchanged thing in the cycle, but you believe that all compilers will know which constant? I think the compiler is unreliable. It is best to do it yourself.
Similarly, the invariance in common functions, such as:
GetLocalHostname (Char * Name) {char * funcname = "getLocalHostName"; sys_log ("% s begin ...", funcname); ... sys_log ("% s end ...", funcname }
If this is a function that is often called, you have to allocate memory every time you call, this overhead is very big. State this variable into static, when the function is called again, it will save the overhead of the distribution of memory, and the execution efficiency is also very good.
13, function name and variable name ------------ I see many programs to name the variable name and function name, especially the variable name, what A, B, C, AA, BB, CC, what FLAG1, FLAG2, CNT1, CNT2, which are also a behavior without "cultivation". Even good comments. A good variable name or a function name, I think there should be the following rules: 1) intuitively and can be spent, and hope that "decoding" will not be "decoded". 2) The length of the name should be the shortest length, but also to maximize its meaning. 3) Don't write all over, don't lower your lowercase, you should write, such as: getLocalHostName or useeraccount. 4) You can be short-handed, but you have to understand, such as: ErrorCode -> Errcode, ServerListener -> Servlisner, Useraccount -> USRACCT, etc. 5) In order to avoid the full bureau function and variable name conflict, you can add some prefixes, usually the module is referred to as a prefix. 6) The global variable is unified to add a prefix or a suffix, let people see this variable knows that it is global. 7) Name the function parameters in Hungarian nomenclature, local variables. But still have to adhere to the principle of "Wangwen Business". 8) Maintain consistent with standard libraries (such as: STL) or development libraries (such as: MFC). 14, the pass value of the function and the pointer ------------ When the function is transferred, when it is incorporated into a non-const, it means that the pointer to modify this pointer in the function. Refers to data in memory. If it is a pass value, then how to modify this value inside the function, it also affects the value that is not passed, because the pass value is only the memory copy.
what? You said this feature, you understand, ok, let's take a look at the routine below:
Voidgetversion (char * pstr) {pstr = malloc (10); strcpy (PSTR, "2.0");}
Main () {char * ver = null; getVersion (Ver); ... ... free (ver);}
I promise that the problem like this is the most important mistake of a novice. The program is in vain through the function getversion to the pointer VER VER VER, but this method does not work at all, the reason is - this is the pass value, not a pointer. You may argue with me, when I divide the pointer? Take a closer look, in fact, what you are passing is that the pointer is actually in the value.
15, modify the cultivation of others -----------
When you maintain the procedure of others, please don't delete or modify the existing program very residual. I often see that some programmers modify the expression or statement directly on others. When modifying others, please do not delete someone else's programs. If you think that others' programs are not correct, please comment, then add your own handlers, you can't know 100% know the intentions of others, so You can recover, please do not rely on CVS or SourceSafe this version control software, or you want to see you the intentions and steps you modify on the source code. This is when the program maintenance, a cultivated programmer should do.
As shown below, this is a better modification:
/ * * ----- Comment by Haoel 2003/04/12 ------ * * char * p = (char *) malloc (10); * MEMSET (p, 0, 10); * / / * ------ Added by Haoel 2003/04/12 ----- * / char * p = (char *) Calloc (10, SizeOf char); / * ---------- ----------------------------- * / ... Of course, this method is used in software maintenance, so Methods, people who can make repatriator easily know the action and intentions of the previous code changes, and this is also a respect for the original author.
Modify someone else's programs in the "Note - Add" manner, it is better to delete the procedures directly.
16, form the same or nearly the same code form function and macro
---------------------
Some people say that the best programmers are the most like "lazy" procedures, which are not reasonable.
If you have some program's code snippet, or just the same, put them in a function. And if this code is not much, and it will be used frequently, you still want to avoid the overhead of the function call, then write him into a macro.
Don't let the same code or functional code exist in multiple places, or if the function changes, you will modify several places, this will bring huge trouble to maintenance, so " Change hundreds of changes, or form a function or macro.
17. Brand in the expression ---------
If you are a more complex expression, you are not very clear, even if you are very clear, please add parentheses, otherwise, others or yourself next time, no Be careful, look at it, understand, in order to avoid this "misunderstanding", and make your own procedure more clear, or plus parentheses.
For example, take the address for a member of a structure:
GetUserage (& (UserInfo-> AGE);
Although, & userinfo-> age, -> The priority of the operator is the highest, add a bracket, it will make people understand what your code means.
For example, a long condition judgment:
IF ((CH [0]> = '0' || CH [0] <= '9') && (CH [1]> = 'a' || CH [1] <= 'Z') && (ch [2]> = 'a' || CH [2] <= 'Z')) Braces, plus spaces and wraps, your code is not easy to read?
18. Const in the function parameters -----------
For some pointer parameters in some functions, if read-only in the function, use const to modify it, so that others will know when you read your function interface, you will know that your intent is [in], if not When constant, the parameter represents [IN / OUT], pay attention to the Const use in the function interface, which is conducive to the maintenance of the program and avoids some errors.
Although const char * p, const char * p, there is no, because your statement is not constant, the content of the pointer can be changed, because the compiler will force the conversion, but plus such a Description, facilitating the reading and compilation of the program. Because in C, a Warning will be reported when modifying the memory pointed to by a const pointer. This will cause the programmer's attention. C is very strict, so much more use of C , using const, constant member functions, constant variables, which will make your code and your program more complete and easy to read. (I will not say more about C constant)
19. The number of parameters (more use structure) -----------------
The number of functional parameters is best not too much. Generally, there are about 6 left and right, and many function parameters will make the people who read the code look very dizziness, and it is not conducive to maintenance. If there are many parameters, please use the structure to deliver parameters. This makes it easy to clean the data package and the simplicity of the program.
It is also beneficial to use the function, because if your function is a lot, such as 12, the caller is easy to make the order and number of parameters, while using the structural struct to transfer parameters, you can regardless of the parameters.
Moreover, the function is easily modified. If you need to add parameters to the function, you don't need to change the function interface, just change the internal processing of the structure and function, and this action is transparent to the program of the call function.
20, the return type of the function, do not omit --------------
When I see a lot of program write functions, I don't pay attention to the return type of the function. If a function does not return a value, please add Void's modification in front of the function. And some programmers are lazy, and what is not modified in the return of Int (because if not modified, the default returns int), this habit is very bad, or for the eEl of the original code, plus int.
Therefore, the return value type of the function is not omitted.
In addition, for Void's functions, we will often forget return, because some C / C compilers are more sensitive, will report some warnings, so even void's function, we should best add Return's statement internally. This contributes to the compilation of the code.
21. Use of GOTO statement ---------
N years ago, a generation of software developed - Dijkstra said: "Goto Statment is Harmful !!" and it is recommended to cancel the goto statement. Because the goto statement is not conducive to the maintenance of the program code.
Here I also strongly recommend not using the goto statement unless the following situation:
#define free (p) i (p) {/ free (p); / p = null; /}
Main () {char * fname, * lname, * mname
FNAME = (char *) Calloc (20, sizeof (char)); if (fname == null) {goto errhandle;}
LName = (char *) Calloc (20, sizeof (char)); if (lname == null) {goto errhandle;} mname = (char *) Calloc (20, sizeof (char)); if (MNAME == Null ) {Goto errhandle;} ... Errhandle: Free (FREE); Free (MNAME); ReportError (err_no_memoey);}
Only in this case, the GOTO statement will make your program easier to read and easier to maintain. (This structure is also encountered when setting the cursor operation in the database with embedded C.
22, macro use ------
Many programmers don't know what it means to "macro" in C? Especially when the macro has parameters, it often confuses the macros and functions. I want to talk about "macro" here, the macro is only a definition. He defines a statement block. When the program is compiled, the compiler first wants to perform a "replace" source of the source and put the macro. Replace the macro defined statement, just like text files. This action term is called "macro"
Using macro is a "danger" because you don't know what the macro will look like. For example, the macro below:
#define max (a, b) a> b? A: B
When we use macros like this, there is no problem: max (num1, num 2); because the macro is turned into Num1> Num2? Num1: Num2; However, if it is called, MAX (17 32, 25 21);, the error occurs when compiling, the reason is that the macro show becomes: 17 32> 25 21? 17 32: 25 21 , Wow, what is this?
Therefore, when the macro is in use, the parameters must be added with parentheses, and the example described above is changed to solve the problem as follows.
#define max ((a), (b)) (a)> (b)? (a) :( b) Even so, don't this macro still have bug, because if I call MAX (i , J ) After this macro, I and J were accumulated twice, this is never what we want. So, in the use of macro, you should also be careful, because the result of the macro show is difficult to make people expect. And though, the macro's execution is quickly (because there is no overhead of the function call), but the macro will rise to the source code, so that the target file size is large, (such as: a 50-row macro, 1000 places in the program) After the macro show will be very good after the opening), the reverse cannot make the program to perform faster (because the execution file is getting bigger, the runtime system is frequently changed).
Therefore, it is necessary to use a function when deciding is a function.