Showing posts with label C. Show all posts
Showing posts with label C. Show all posts

C/C++ Coding Standard



Naming Convenion

  1.  匈牙利命名法
    1. http://blog.udn.com/start8588/1171731
  2.  駝峰式
    1. https://zh.wikipedia.org/wiki/%E9%A7%9D%E5%B3%B0%E5%BC%8F%E5%A4%A7%E5%B0%8F%E5%AF%AB


Documentation

  1. Software design document (SDD)
  2. Doxygen




相關文件

  • Book
    • https://sites.google.com/site/cinterfacesimplementations/
  • Indian Hill C Style Guide
    • http://www.cs.arizona.edu/~mccann/cstyle.html
  • Linux
    • https://www.kernel.org/doc/Documentation/CodingStyle
  • GNU
    • http://www.gnu.org/prep/standards/standards.html
  • NASA
    • http://homepages.inf.ed.ac.uk/dts/pm/Papers/nasa-c-style.pdf
  • Google
    • https://github.com/google/styleguide
    • https://google-styleguide.googlecode.com/svn/trunk/cppguide.html
  • Others
    • http://users.ece.cmu.edu/~eno/coding/CCodingStandard.html
    • http://www.possibility.com/Cpp/CppCodingStandard.html
    • https://www.doc.ic.ac.uk/lab/cplus/cstyle.html
    • http://www.maultech.com/chrislott/resources/cstyle/

Variable Attributes

Aligned Variable


char tmpBuf[BLOCKSIZE] __attribute__((__aligned__(ALIGNMENT)));
char *tmpBuf = (char*) memalign(ALIGNMENT, BLOCKSIZE);



相關文件

mmap vs munmap

除錯, Debug, syslog, GDB, gprof

DEBUG MACRO

e.g.

#define BASIC_DEBUG 1
#define EXTRA_DEBUG 2
#define SUPER_DEBUG 4

#if (DEBUG & EXTRA_DEBUG)
.................
#endif


  • Use the compiler to define the DEBUG such as -DDEBUG=5

assert

善用assert巨集,判斷程式執行正確。assert 會將錯誤資訊送到stderr,隨後呼叫abort終止程式

e.g.
#include <assert.h>
void assert(int expression);

利用NDEBUG來定義assert這個巨集,如果NDEBUG被定義,就會取消assert定義。所以在編譯過程中,如果加上-DNDEBUG或是在程式碼assert.h之前加入 #define NDEBUG,就會關閉assertion的動作

syslog

當程式無法將錯誤訊息輸出到stdout 或是 stderr 時,善用syslog

e.g.
#include <syslog.h>
void syslog(int priority,char *format,...);
void openlog( char *ident, int option, int  facility);
void closelog( void );

GDB


e.g.

  1. gcc -g -o xxx xxx.c
  2. gdb
  3. (gdb)file ./xxx
  4. r


e.g.
  1. gcc -g -o xxx xxx.c
  2. gdb --args ./add 3 5
  3. r

e.g.

core dump,檔案名稱為core,這是程式的記憶體映像


  • r = (run)執行一個程式
  • bt = (backtrace)堆疊追蹤
  • p = (print)檢驗變數
  • l = (list)程式列表
  • b = (break)設定中斷點
  • c = (cont)讓程式繼續執行
  • display 程式在遇到中斷點而停止時,自動顯示陣列數值

  • commands ... end 指定一些命令,這些命令會在遇到中斷點時被執行
  • info display 查看display的狀況
  • info break 查看中斷點的狀況
  • disable break 1  暫停中斷點1


gprof

Use gprof to profiling C program on Ubuntu 12.04

e.g.

  1. gcc -pg xxx.c -o xxx
  2. ./xxx          # it will generate gmon.out at this step
  3. gprof xxx gmon.out > xxx.gprof          # use gprof to generate document
  4. vim xxx.gprof


ctags

cxref

cflow

ElectricFence Library - 記憶體除錯

**Valgrind - 偵測陣列錯誤存取與記憶體除錯

e.g.

$ valgrind --leak-check=yes -v ./add_vec

相關文件

The C Preprocessor

4. Conditionals

  • A program may need to use different code depending on the machine or operating system it is to run on. In some cases the code for one operating system may be erroneous on another operating system; for example, it might refer to data types or constants that do not exist on the other system. When this happens, it is not enough to avoid executing the invalid code. Its mere presence will cause the compiler to reject the program. With a preprocessing conditional, the offending code can be effectively excised from the program when it is not valid.
  • You may want to be able to compile the same source file into two different programs. One version might make frequent time-consuming consistency checks on its intermediate data, or print the values of those data for debugging, and the other not.
  • A conditional whose condition is always false is one way to exclude code from the program but keep it as a sort of comment for future reference.
  • e.g.
    • #ifdef
    • #ifndef
    • #endif
  • e.g.
    • #if (!defined(_DEBUG) && defined(USE_MYLIB))
    • #endif
    • 好處: 可同時檢測多個預編譯變數
  • e.g.
    • #if
    • #else
    • #endif
  • e.g.
    • #if
    • #elif
    • #elif
    • #else
    • #endif
  • Delete codes
    • #if 0
    • #endif

5. Diagnostics (診斷)

  • #error
    • The directive ‘#error’ causes the preprocessor to report a fatal error ( enforce the compiler stopping compile ). The tokens forming the rest of the line following ‘#error’ are used as the error message.
    • #ifdef  A
    • #error "ERROR A"
    • #endif
  • #warning
    • The directive ‘#warning’ is like ‘#error’, but causes the preprocessor to issue a warning and continue preprocessing. The tokens following ‘#warning’ are used as the warning message.

6. #line

  • The C preprocessor informs the C compiler of the location in your source code where each token came from.
  • e.g.
    • #line linenum
    • #line linenum filename
    • #line anything else

7. #pragma

  • The method specified by the C standard for providing additional information to the compiler.
  • e.g. #pragma token-sequence
    • If token-sequence exist, then doing the correspond action.

8. #ident


9.#using


10. Operator in preprocessor

  • #
    • stringizing operator
  • ##
    • token pasting operator
  • define()

11. Miscellaneous directive

  • #pragma
  • #line
  • #error

gcc 編譯過程


一個編譯過程通常需要4道程序
  1. 預處理 (Pre-Processing) 先處理那些#ifdef #define這些東西並做一些巨集代換
  2. 編譯 (Compiling) 做語意分析,翻譯成組合語言
  3. 彙編 (Assembling) 翻成機器碼與OS有關的格式,做成relocatable obj檔
  4. 鏈接 (Linking)  找到symbol(函式,變數名)與程式庫(shared obj)中的副程式 ,做成可執行obj檔(executable obj)

  • gcc -Wall -pedantic -ansi  (常用)



e.g.

Syntax

#define identifier replacement-list(optional)(1)
#define identifier( parameters ) replacement-list(2)
#define identifier( parameters, ... ) replacement-list(3)(since C99)
#define identifier( ... ) replacement-list(4)(since C99)
#undef identifier(5)

Explanation

#define directives

The #define directives define the identifier as a macro, that is they instruct the compiler to replace all successive occurrences of identifier with replacement-list, which can be optionally additionally processed. If the identifier is already defined as any type of macro, the program is ill-formed unless the definitions are identical.
Object-like macros
Object-like macros replace every occurrence of a defined identifier with replacement-list. Version (1) of the #definedirective behaves exactly like that.
Function-like macros
Function-like macros replace each occurrence of a defined identifier with replacement-list, additionally taking a number of arguments, which then replace corresponding occurrences of any of the parameters in the replacement-list. The number of arguments must be the same as the number of arguments in the macro definition (parameters) or the program is ill-formed. If the identifier is not in functional-notation, i.e. does not have parentheses after itself, it is not replaced at all.
Version (2) of the #define directive defines a simple function-like macro.
Version (3) of the #define directive defines a function-like macro with variable number of arguments. The additional arguments can be accessed using __VA_ARGS__ identifier, which is then replaced with arguments, supplied with the identifier to be replaced.
Version (4) of the #define directive defines a function-like macro with variable number of arguments, but no regular arguments. The arguments can be accessed only with __VA_ARGS__ identifier, which is then replaced with arguments, supplied with identifier to be replaced.

# and ## operators

In function-like macros, a # operator before an identifier in the replacement-list runs the identifier through parameter replacement and encloses the result in quotes, effectively creating a string literal. In addition, the preprocessor adds backslashes to escape the quotes surrounding embedded string literals, if any, and doubles the backslashes within the string as necessary. All leading and trailing whitespace is removed, and any sequence of whitespace in the middle of the text (but not inside embedded string literals) is collapsed to a single space. This operation is called "stringification". If the result of stringification is not a valid string literal, the behavior is undefined.
When # appears before __VA_ARGS__, the entire expanded __VA_ARGS__ is enclosed in quotes:
#define showlist(...) puts(#__VA_ARGS__)
showlist();            // expands to puts("")
showlist(1, "x", int); // expands to puts("1, \"x\", int")
(since C99)
## operator between any two successive identifiers in the replacement-list runs parameter replacement on the two identifiers and then concatenates the result. This operation is called "concatenation" or "token pasting". Only tokens that form a valid token together may be pasted: identifiers that form a longer identifier, digits that form a number, or operators + and = that form a +=. A comment cannot be created by pasting / and * because comments are removed from text before macro substitution is considered. If the result of concatenation is not a valid token, the behavior is undefined.
Note: some compilers offer an extension that allows ## to appear after a comma and before __VA_ARGS__, in which case the ## does nothing when __VA_ARGS__ is non-empty, but removes the comma when __VA_ARGS__ is empty: this makes it possible to define macros such as fprintf (stderr, format, ##__VA_ARGS__)



Macro offsetof


#include
#define offsetof(type, member) (size_t)&(((type*)0)->member)



Macro container_of


#include <linux/kernel.h>
#define container_of(ptr, type, member) ({ \
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
     (type *)( (char *)__mptr - offsetof(type,member) );})    


相關文件

Program Elapsed time


#include <stdio.h>
#include <time.h>
clock_t start = clock();
/* Code you want timed here */
printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC);

Reduce execution time of a C program?



1) Use the right algorithms. Look into the Big O efficiency of any algorithms you are using, and make sure there aren't more efficient algorithms available. 

2) Think about trading using more memory for a faster algorithm. Perhaps pre-computing tables of intermediate results. 

3) Use a profiler to see where the bottle necks are and try improving them. 

4) Optimize the inner most loops using assembly language to get the last little bit faster. 

5) Run it on a faster computer. 

6) Make it run in parallel across many computers or CPUs. This is especially good on the newer Intel chips where you have access to multiple CPUs on one chip. Distributed network computing sometimes is a good idea. Cloud computing is another possibility these days. 

7) Make sure that C really is the right answer. It might not be in all cases. 

Read more: http://wiki.answers.com/Q/How_do_you_reduce_execution_time_of_a_C_program#ixzz24RwdgPVY

itoa()

char* itoa(int val, int base){
 
     static char buf[32] = {0};
 
     int i = 30;
 
     for(; val &amp;&amp; i ; --i, val /= base)
 
          buf[i] = "0123456789abcdef"[val % base];
 
     return &amp;buf[i+1];
 
}


Powerd by: http://tohtml.com/