Assert. h
The assert macro defines two expressions:
# Define assert (exp )? (Void) 0: _ assert (msg ))
# Define assert (exp) (void) (exp) | _ assert (msg ))
Ctype. h
1. Development History:
(If (0 <= c & c <= '9'), frequently used code that is too long and has not been reused)
Function-differentiated character classes (isalpha (c) calls are too frequent, affecting program execution time)
Macro definition (saving execution time, But encountering some problems)
2. Problems with macro definition
- The amount of Code Compiled by programmers is small, but the amount of compiled code is large.
- Subexpressions may be split due to tight binding.
- Parameters may be executed multiple times rather than expected (for example, getc, putc, ++, --, etc)
3. Use a conversion table
Character c is compiled into the index of the conversion table named _ ctype. Different characters of each table item are indexed characters. If any bit corresponding to mask _ XXXMARK is set, that character is in the test category. For all the correct parameters, the macro is expanded into a compact non-zero expression.
_UPPER 0x1 /* upper case letter */ _LOWER 0x2 /* lower case letter */ _DIGIT 0x4 /* digit[0-9] */ _SPACE 0x8 /* tab, carriage return, newline, */ _PUNCT 0x10 /* punctuation character */ _CONTROL 0x20 /* control character */ _BLANK 0x40 /* space char */ _HEX 0x80 /* hexadecimal digit */ _LEADBYTE 0x8000 /* multibyte leadbyte */ _ALPHA (0x0100|_UPPER|_LOWER) /* alphabetic character */
unsigned *_pctype = _ctype+; unsigned *_pwctype = _ctype+; unsigned _ctype[] = , _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _SPACE+_CONTROL, _SPACE+_CONTROL, _SPACE+_CONTROL, _SPACE+_CONTROL, _SPACE+_CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _CONTROL, _SPACE+_BLANK, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _DIGIT+_HEX, _DIGIT+_HEX, _DIGIT+_HEX, _DIGIT+_HEX, _DIGIT+_HEX, _DIGIT+_HEX, _DIGIT+_HEX, _DIGIT+_HEX, _DIGIT+_HEX, _DIGIT+_HEX, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _UPPER+_HEX, _UPPER+_HEX, _UPPER+_HEX, _UPPER+_HEX, _UPPER+_HEX, _UPPER+_HEX, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _UPPER, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _LOWER+_HEX, _LOWER+_HEX, _LOWER+_HEX, _LOWER+_HEX, _LOWER+_HEX, _LOWER+_HEX, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _LOWER, _PUNCT, _PUNCT, _PUNCT, _PUNCT, _CONTROL, };
isalpha(_c) ( _pctype[_c] & (_UPPER|_LOWER) ) isupper(_c) ( _pctype[_c] & _UPPER ) islower(_c) ( _pctype[_c] & _LOWER ) isdigit(_c) ( _pctype[_c] & _DIGIT ) isxdigit(_c) ( _pctype[_c] & _HEX ) isspace(_c) ( _pctype[_c] & _SPACE ) ispunct(_c) ( _pctype[_c] & _PUNCT ) isalnum(_c) ( _pctype[_c] & (_UPPER|_LOWER|_DIGIT) ) isprint(_c) ( _pctype[_c] & (_BLANK|_PUNCT|_UPPER|_LOWER|_DIGIT) ) isgraph(_c) ( _pctype[_c] & (_PUNCT|_UPPER|_LOWER|_DIGIT) ) iscntrl(_c) ( _pctype[_c] & _CONTROL )
_tolower(_c) ( (_c)-'A'+'a' ) _toupper(_c) ( (_c)-'a'+'A' )
4. Possible Table Conversion Problems
The disadvantage of this method is that for some wrong parameters, macros will generate wrong code. If a macro parameter is not in its definition field, when the macro is executed, it will access the storage space outside the conversion table.
For example, when some uncommon character codes are tested, if the symbol bit is set to, the parameter will be a negative value outside the definition field of the function.
Exercise caution when handling the EOF symbol.
The book does not seem to mention the solution to the problem encountered in the implementation of the conversion table-_-|
5. region settings
When the region settings change, our character classes may also change accordingly.
6. static storage space
The database can use writable static storage space pointing to the table pointer, but we cannot share the same data object in different control lines in the program.
The above implementation does not use static storage space.
7. Are macros used in practice?
The mingw implementation is not a macro. The Code is as follows:
__ISCTYPE(c, mask) (MB_CUR_MAX == 1 ? (_pctype[c] & mask) : _isctype(c, mask)) __cdecl __MINGW_NOTHROW isalnum( c) { __ISCTYPE(c, (_ALPHA| __cdecl __MINGW_NOTHROW isalpha( c) { __cdecl __MINGW_NOTHROW iscntrl( c) { __cdecl __MINGW_NOTHROW isdigit( c) { __cdecl __MINGW_NOTHROW isgraph( c) { __ISCTYPE(c, (_PUNCT|_ALPHA| __cdecl __MINGW_NOTHROW islower( c) { __cdecl __MINGW_NOTHROW isprint( c) { __ISCTYPE(c, (_BLANK|_PUNCT|_ALPHA| __cdecl __MINGW_NOTHROW ispunct( c) { __cdecl __MINGW_NOTHROW isspace( c) { __cdecl __MINGW_NOTHROW isupper( c) { __cdecl __MINGW_NOTHROW isxdigit( c) { __ISCTYPE(c, _HEX);}
The implementation of inline functions is more secure than macros. In addition, the preprocessing work is handed over to the compiler so that the compiler can automatically choose between the amount of code and the efficiency of code.