ISO-ANSI CC++ 预处理器测试文本

    技术2022-05-11  24

    ISO-ANSI C/C++ 预处理器测试文本

    http://blog.csdn.net/huyansoft/archive/2009/04/01/4039976.aspx

     

    A test file for my ISO C/C++ PreprocessorCopyright(c) 2008, HuYanAll rights reserved.

    Trigraph------------------------------------------------------------------------------------------------------------------------

    in normal textint a ??( ??) = ??< 1, 2, 3 ??>;    //equivalent to next lineint a [ ] = { 1, 2, 3 };

    in preprocessing directives??=define MACRO_TRIGRAPH(a,b)  a ??=??= b    //equivalent to next line#define MACRO_TRIGRAPH(a,b)  a ## b

    in comments/* ??=  ??)  ??!  ??(  ??'  ??>  ??/n  ??<  ??- */    //equivalent to next line/* #  ]  |  [  ^  }  /n  {  ~ */

    in backslashch??/ar* s="string ??/literal";

    equivalent toch/ar* s="string /literal";

    and equivalent tochar* s="string literal";

    Backslash------------------------------------------------------------------------------------------------------------------------

    in normal textch/ar* s="string /literal";

    equivalent tochar* s="string literal";

    in preprocessing directives#/defi/ne MACRO_/BACKSLASH/(a,b)  a #/# b

    equivalent to#define MACRO_BACKSLASH(a,b)  a ## b

    in comments//a single-/line comment

    ///a single-line comment

    //*a multi-line comment*//

    in the end of filenext backslash is unexpected if it is the last character of this file/

    next backslash is unexpected if next newline is the end of this file/

    Single-line comment-----------------------------------------------------------------------------------------------------------------------

    in characters constant and string literal'a//b'    //a characters constant, not syntax error"a//b"    //4 characters string literal, not syntax error

    between tokens (replacement to a space)m=n//**/o     //equivalent to m=n , not equivalent to m=n/o

    in header name (error)#include <file.h//>    //undefined behavior, not equivalent to #include <file.h>#include "file.h//"    //undefined behavior, not equivalent to #include <file.h>

    attempt defined it as macro (error)#define SINGLE_LINE_COMMENT // SINGLE_LINE_COMMENT abc    //error, 'abc' not comment

    #define GLUE(x,y) x##yGLUE(/,/) abc     //error, 'abc' not comment

    Multi-line comment------------------------------------------------------------------------------------------------------------------------

    in characters constant and string literal'a//b'    //a characters constant, not syntax error"a/**/b"    //6 characters string literal, not syntax error

    between tokens (replacement to a space)/**/#/**/define/**/MACRO_COMMENT/**/replacement/**/list/**/    //equivalent to next line # define MACRO_COMMENT replacement list

    within punctuator or identifier (error)i+/**/+    //equivalent to i+ +, not equivalent to i++#incl/**/ude <file.h>    //error, equivalent to #incl ude <file.h>

    in header name (error)#include <file.h/**/>    //undefined behavior, not equivalent to #include <file.h>#include "file.h/**/"    //undefined behavior, not equivalent to #include <file.h>

    nesting/*****************************/    //ok/* // */    //ok,a multi-line comment/* /**/ */    //error, multi-line comments do not nest ('*/' found outside of comment)

    //    /**/    //error, '*/' found outside of comment

    //attempt defined it as macro (error)#define BEGIN_COMMENT /*#define END_COMMENT */BEGIN_COMMENT abc END_COMMENT    //error, 'abc' not comment

    Identifier----------------------------------------------------------------------------------------------------------------------------------

    _ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz    //an identifier/u1234_/uABCD_/U00001234_/U0000abcd    //an identifier (contains universal character names)

    Preprocessing operator or punctuator--------------------------------------------------------------------------------------------------------

    parsing>>=++++    //three punctuators, '>>=' and two '++'x+++++y    //parsed as x ++ ++ + y (although this expression is invalid), not x ++ + ++ y

    reserved operator#define delete DELETE   //error, 'delete' is an operator in C++, not an identifier

    Preprocessing number------------------------------------------------------------------------------------------------------------------------

    familiar123L   //valid preprocessing number, a long integer.123   //valid preprocessing number, a floating number0123   //valid preprocessing number, a octal number0x123abc   //valid preprocessing number, a hexadecimal number3.14e10   //valid preprocessing number3.14e+10   //valid preprocessing number3.14E-10   //valid preprocessing number

    definition123.456._.abc.ABC.e+.e-.E+.E-    //valid preprocessing number.123.456._.abc.ABC.e+.e-.E+.E-    //valid preprocessing number./u1234_/uABCD_/U00001234_/U0000abcd    //a preprocessing number (contains universal character names)

    +123    //not a preprocessing number-123    //not a preprocessing number123+    //not a preprocessing number123-    //not a preprocessing number

    importance#define X123  4560X123    //'X123' is not an identifier and will not be expanded, because '0X123' is a preprocessing number

    Header name-------------------------------------------------------------------------------------------------------------------------------

    parsing#include <file.h>=        //'>=' is not a punctuator because <file.h> is a header namea < b && c > d        //< b && c > is not a header name#if a < b && c > d        //< b && c > is not a header name#endif

    matching#include <file.h    //error, missing matched separator#include "file.h    //error, missing matched quotes#include L"file.h"    //error, unexpected 'L'

    unexpected characters in header names#include <' / " // /* >    //undefined behavior#include " ' /  // /* "    //undefined behavior

    processing before string connecting#define BASE_NAME "file"#define EXTEND_NAME ".h"#include BASE_NAME EXTEND_NAME    //equivalent to #include "file" ".h" , but not equivalent to #include "file.txt"

    Character constant------------------------------------------------------------------------------------------------------------------------

    empty character (error)''    //errorL''    //error

    matching'    //error, missing matched single-quotesL'    //error, missing matched single-quotes'abc/'    //error, missing matched single-quotes, /' is only a escape sequenceL'abc/'    //error, missing matched single-quotes, /' is only a escape sequence

    escape sequences'/a /b /f /n /r /t /v /' /" /? //'    //valid escape sequences'/c /d /e / /+'    //invalid escape sequences' ? " '    //ok, may represented by ' /? /" '

    value range of escape sequences'/400'    //error, too large value of octal escape sequence'/377'    //okL'/777'    //ok

    '/x100'    //error, too large value of hexadecimal escape sequence'/xff'   //okL'/x10000'    //error, too large value of escape hexadecimal sequenceL'/xffff'    //ok

    String literal----------------------------------------------------------------------------------------------------------------------------

    empty string""    //okL""    //ok

    matching"    //error, missing matched quotesL"    //error, missing matched quotes"abc/"    //error, missing matched quotes, /" is only a escape sequenceL"abc/"   //error, missing matched quotes, /" is only a escape sequence

    escape sequences"/a /b /f /n /r /t /v /" /" /? //"    //valid escape sequences"/c /d /e / /+"    //invalid escape sequences" ? ' "    //ok, may represented by " /? /' "

    value range of escape sequences"/400"    //error, too large value of octal escape sequence"/377"    //okL"/777"    //ok

    "/x100"    //error, too large value of hexadecimal escape sequence"/xff"   //okL"/x10000"    //error, too large value of escape hexadecimal sequenceL"/xffff"    //ok

    Universal character name-----------------------------------------------------------------------------------------------------------------------

    within identifier/u1234_/uABCD_/U00001234_/U0000abcd    //valid

    within character constant'/u1234_/uABCD_/U00001234_/U0000abcd'    //valid

    within string literal"/u1234_/uABCD_/U00001234_/U0000abcd"    //valid

    within preprocessing number./u1234_/uABCD_/U00001234_/U0000abcd    //valid

    value range/u0065_/U00000065    //error, a universal character name cannot designates a basic source character (uncompleted)'/u0065 /U00000065'    //error, a universal character name cannot designates a basic source character (uncompleted)"/u0065 /U00000065"    //error, a universal character name cannot designates a basic source character (uncompleted)./u0065_/U00000065    //error, a universal character name cannot designates a basic source character (uncompleted)

    /u0019_/u007f_/u009f_/U00000019_/U0000007f_/U0000009f    //error, a universal character name cannot less than 0x20, or in the range 0x7F-0x9F'/u0019 /u007f /u009f /U00000019 /U0000007f /U0000009f'    //error, a universal character name cannot less than 0x20, or in the range 0x7F-0x9F"/u0019 /u007f /u009f /U00000019 /U0000007f /U0000009f"    //error, a universal character name cannot less than 0x20, or in the range 0x7F-0x9F./u0019_/u007f_/u009f_/U00000019_/U0000007f_/U0000009f    //error, a universal character name cannot less than 0x20, or in the range 0x7F-0x9F

    Preprocessing directive and normal text--------------------------------------------------------------------------------------------------------

    null directive#    //no effect

    normal text#define EMPTYEMPTY #include <file.h>    //a text line, will expend to #include <file.h> but not a preprocessing directive

    #define INCLUDE1 #include <file.h>INCLUDE1    //a text line, will expend to #include <file.h> but not a preprocessing directive

    #define INCLUDE2 #includeINCLUDE2 <file.h>    //a text line, will expend to #include <file.h> but not a preprocessing directive

    directive name#define INCLUDE3 include <file.h>#INCLUDE3    //error, nonexistent directive name

    #define INCLUDE4 include#INCLUDE4 <file.h>    //error, nonexistent directive name

    #define pragma error#pragma "abc"    //the directive name is 'pragma' but not 'error', because the replacement was not occured

    Source file inclusion---------------------------------------------------------------------------------------------------------------------------

    #define MAKE_HEADER(s) #s#include MAKE_HEADER(file.h)     //ok, macro expanded, the header name is "file.h"

    //#include "stdio.h"    //working but warning

    //#line __LINE__ "new.h"    //next line is error even if current line is reserved#include "test.txt"    //error, cannot include itselt, though current file name was modified to "new.h" by last line

    #include "b.txt"    //begin a recursive inclusion, b.txt and c.txt will include each other

    Conditional inclusion---------------------------------------------------------------------------------------------------------------------------

    syntax checking in skipped groups#if 0                            //checking carefully and responsibly even if in skipped groups    "abc                         //fogot a quotes    '/400'                       //too large value of octal escape sequence    #include <d:/file.h>         //unexpected '/' character    #define PI3.14               //forgot spaces after PI    #define MAX(a,a)  a>b?a:b    //careless spelling of second parameter    #define defined otherwise    //do not know identifier 'defined' is reserved    #line "file.h" 100           //two arguments reversed#elsc                            //careless spelling, follow lines before #endif will be ignored unecpectly    #define PI 3.14              //ignored unecpectly#endif

    unreplaced macros#define UNREPLACED something

    #ifdef UNREPLACED    //UNREPLACED will not be expanded#endif

    #ifndef UNREPLACED    //UNREPLACED will not be expanded#endif

    #if defined(UNREPLACED)    //UNREPLACED will not be expanded#elif defined(UNREPLACED)    //UNREPLACED will not be expanded#endif

    matching#endif    //error, missing matched 'if' branch#else    //error, missing matched 'if' branch#elif 1    //error, missing matched 'if' branch

    #if 0#elif 0#else//#elif 0    //error if this line reserved, 'elif' branch shall not occur after 'else' branch#endif    //dismatch if this line is removed

    branch testing#define A#ifndef A #ifdef B  a if #elif 0  a elif a #elif 1  a elif b #else  a else #endif#elif 0 #ifdef b  b if #elif 0  b elif a #elif 1  b elif b #else  b else #endif#elif 1 #ifdef c  c if #elif 0  c elif a #elif 1  c elif b #else  c else #endif#else #ifdef d  d if #elif 1  d elif a #elif 1  d elif b #else  d else #endif#endif

    Macro definition-----------------------------------------------------------------------------------------------------------------------------

    white separator#define PI3.14    //invalid directive format, forgeting space after macro name#define PI()3.14    //invalid directive format, forgeting space after ')'#define MACRO_MAX (a,b) ((a)>(b)?(a):(b))    //will be defined as object-like macro, not function-like macro

    redefinition#define ERR_PARA(a,a)  something        //error, parameter 'a' redefined

    #define OBJECT_LIKE something#define OBJECT_LIKE() something    //error, cannot redefine object-like macro as function-like macro

    #define FUNCTION_LIKE() something#define FUNCTION_LIKE something    //error, cannot redefine function-like macro as object-like macro

    #define OBJ_LIKE (1)#define OBJ_LIKE (0)    //error, redefine with different token sequence in replacement list

    #define FUNC_LIKE(a) something#define FUNC_LIKE(b) something    //error, redefine with different parameter list

    #define MACRO_CONNECT(a,b,c) a##b##c#define MACRO_CONNECT( a , b , c )  a ## b ## c    //ok, the same definition to MACRO_CONNECT (uncompleted)

    Macro invocation and replacement-----------------------------------------------------------------------------------------------------------------------------

    #define MULTI_ARGS(a,b) b,aMULTI_ARGS    //valid text, but not a macro invocation

    arguments numberMULTI_ARGS()    //warning, not enough argumentsMULTI_ARGS(1,)    //valid, the second argument is emptyMULTI_ARGS(,2)    //valid, the first argument is emptyMULTI_ARGS(,)    //valid, both arguments are emptyMULTI_ARGS(1,2,3,4)    //valid, though arguments too much

    whites (spaces, tabs and newlines) within argumentsMULTI_ARGS (    //valid, though whites involved  1  ,    2  )

    quotes matching//MULTI_ARGS(a,b    //error, missing matched ')'//MULTI_ARGS( isdigit(32), isdigit(65)    //error, missing matched ')'MULTI_ARGS( isdigit(32), isdigit(65) )    //valid, four middle parentheses skippedMULTI_ARGS( MULTI_ARGS(1,2), MULTI_ARGS(3,4) )    //valid, nesting invocation (will expand to 4,3,2,1)MULTI_ARGS(    1,    #define PI 3.14    //error, preprocessing directives cannot occur within a macro invocation    )

    replacement time#define MACROX 2#define MACROY MACROX    //MACROX does not replaced to 2 now#undef  MACROX#define MACROX 3int i=MACROY;    //replacement occurs, MACROY will expanded to 3 but not 2

    The # operator (string making)----------------------------------------------------------------------------------------------------------------

    definition#define ERR_JIN1(a) #    //error, # should be followed by a parameter in the replacement list of a function-like macro (uncompleted)#define ERR_JIN2(a) a#b    //error, # should be followed by a parameter in the replacement list of a function-like macro (uncompleted)

    whites (spaces, tabs and newlines) within arguments#define MKS(s) #sMKS(abc)    //expands to "abc"MKS(  abc  )    //expands to "abc", whites before the first token and after the last token within the argument is deletedMKS(abc)    //expands to "abc", (uncompleted)MKS(  a    b    c  )    //expands to "a b c", each white within the argument becomes a single space

    arguments substitution#define S1(s) #s#define S2(s) S1(s)#define MYNAME huyanS1( MYNAME )    //expands to "MYNAME"S2( MYNAME )    //expands to "huyan"

    #define FORMAT(x) #x "=%d/n",x#define MYNUM 100printf( FORMAT(MYNUM) )    //expands to printf( "MYNUM" "=%d/n",100 ), not printf( "100" "=%d/n",100 )

    making valid string literal#define S3(s) #sprintf("%s", S3(a/nb "a/nb" // '//' /n '/n'));    //expands to next lineprintf("%s", "a/nb /"a//nb/" // '' /n '//n'");    //not next sick line//printf("%s", "a/nb "a/nb" // '//' /n '/n'");    //error, dismatched quotes

    The ## operator (token connection)------------------------------------------------------------------------------------------------------------

    definition#define ERR_JINJIN1(a) ## a    //error, ## cannot occur at the beginning of the replacement list#define ERR_JINJIN2(a) a ##    //error, ## cannot occur at the end of the replacement list

    #define hash_hash1 ##    //error, cannot define ## to a macro directly#define hash_hash2 # ## #    //okhash_hash2    //expands to ##

    arguments substitution#define CONNECT(x) I ## x#define CONNECT2(x) CONNECT(x)#define S(a) a#define IS(a) aint I2=5;CONNECT( S(1) )    //expands to IS(1), and further expands to 1CONNECT2( S(2) )    //expands to CONNECT2( 2 ), further expands to CONNECT( 2 ), and last expands to I2

    example from ISO C Standard#define hash_hash # ## ##define mkstr(a) # a#define in_between(a) mkstr(a)#define join(c, d) in_between(c hash_hash d)char p[] = join(x, y);    //equivalent to char p[] = "x ## y";

    Complex macro replacement (rescanning and further replacement)---------------------------------------------------------------------------------

    #define MACROS(a) a#define MACROT(b) b*bMACROS ( MACROT ) ( 3 )    //expands to 3*3

    int M1=3;#define M1 M2#define M2 M1*M1    //recursive definitionprintf("%d/n",M1);    //expands to M1*M1 and output 9

    #define Puts(s)  printf("%s is ",#s); Puts(s)char translator[]={-70,-6,-47,-27,0};Puts(translator);    //expands to  printf("%s is","translator"); Puts(translator);

    example from ISO C Standard#define X       3#define F(a)    F(X  *  (a))#undef  X#define X       2#define G       F#define Z       Z[0]#define H       G(~#define M(a)    a(W)#define W       0,1#define T(a)    a#define P()     int#define Q(x)    x#define R(x,y)  x ## y#define STR(x)  # x

    F(y+1) + F(F(Z)) % T(T(G)(0) + T) (1);                //expands to F(2 * (y+1)) + F(2 * (F(2 * (Z[0])))) % F(2 * (0)) + T(1);G(X+(3,4)-W) | H 5) & M(F)^M(M);                      //expands to F(2 * (2+(3,4)-0,1)) | F(2 * (~ 5)) & F(2 * (0,1))^M(0,1);P() i[Q()] = { Q(1), R(2,3), R(4,), R(,5), R(,) };    //expands to int i[] = { 1, 23, 4, 5,  };char c[2][6] = { STR(hello), STR() };                 //expands to char c[2][6] = { "hello", "" };

    #define Str(s) # s#define Xstr(s) Str(s)#define Debug(s, t) printf("x" # s "= %d, x" # t "= %s", x ## s, x ## t)#define INCFILE(n) vers ## n#define Glue(a, b) a ## b#define Xglue(a, b) Glue(a, b)#define HIGHLOW "hello"#define LOW LOW ", world"

    Debug(1, 2);                                                      //expands to printf("x" "1" "= %d, x" "2" "= %s", x1, x2);fputs(Str(strncmp("abc/0d", "abc", '/4') == 0) Str(: @/n), s);    //expands to fputs("strncmp(/"abc//0d/", /"abc/", '//4') == 0" ": @/n",s);#include Xstr(INCFILE(2).h)                                       //expands to #include "vers2.h"Glue(HIGH, LOW);                                                  //expands to "hello";Xglue(HIGH, LOW)                                                  //expands to "hello" ", world"

    Macro with variable arguments-----------------------------------------------------------------------------------------------------------------------

    definition#define ERR_VAM1  __VA_ARGS__    //error, unexpected __VA_ARGS__ in the replacement list of normal macro#define ERR_VAM2(a,b,c) __VA_ARGS__     //error, unexpected __VA_ARGS__ in the replacement list of normal macro#define ERR_VAM3(a,b,c,...) a,b,c       //warning, missing __VA_ARGS__ in the replacement list of variable arguments macro

    #define ERR_VAM4(__VA_ARGS__) something     //error, the parameter cannot be __VA_ARGS__#define ERR_VAM5(__VA_ARGS__,...) __VA_ARGS__     //error, the parameter cannot be __VA_ARGS__

    #define __VA_ARGS__  otherwise    //error, the identifier '__VA_ARGS__' is reserved#undef __VA_ARGS__    //error, the identifier '__VA_ARGS__' is reserved

    #define VAM1(...)  __VA_ARGS__    //ok#define VAM2(a,b,c,...) __VA_ARGS__    //ok

    arguments substitution#define VAM3(...)  #__VA_ARGS__VAM3()    //expands to ""VAM3(1)    //expands to "1"VAM3(a,b,c)    //expands to "a,b,c"

    #define VAM4(a,b,...) a b #__VA_ARGS__VAM4(1)    //warning, not enough argumentsVAM4(1,2)    //expands to 1 2 ""VAM4(1,2,3,4,5)    //expands to 1 2 "3,4,5"VAM4( ((a), (b)), ((c), (d)), ((e),(f)), ((g),(h)) )    //expands to ((a), (b)) ((c), (d)) "((e),(f)), ((g),(h))"

    example from ISO C Standard#define Debug2(...) fprintf(stderr, __VA_ARGS__)#define Showlist(...) puts(#__VA_ARGS__)#define Report(test, ...) ((test)?puts(#test):printf(__VA_ARGS__))

    Debug2("Flag");                                   //expands to fprintf(stderr, "Flag" );Debug2("x = %d/n", x);                            //expands to fprintf(stderr, "x = %d/n", x );Showlist(The first, second, and third items.);    //expands to puts( "The first, second, and third items." );Report(x>y, "x is %d but y is %d", x, y);         //expands to ((x>y)?puts("x>y"):printf("x is %d but y is %d", x, y));

    Predefined macro names and reserved identifiers------------------------------------------------------------------------------------------------

    following predefined macros will be expanded__DATE____FILE____LINE____STDC____STDC_HOSTED____STDC_VERSION____TIME__

    redefine and undefine (error)#define __DATE__  otherwise       //error, cannot redefine predefined macros#define defined  otherwise        //error, the identifier 'defined' is reserved

    #undef __DATE__       //error, cannot undefine predefined macros#undef defined        //error, the identifier 'defined' is reserved

    Line control-----------------------------------------------------------------------------------------------------------------------------------

    //#line 100    //set next line number to 100//#line 200 "file1.h"    //set next line number to 200 and current file name to "file1.h"

    expanded macro arguments#define LINE_NUMBER1 300//#line LINE_NUMBER1    //set next line number to 300 (the macro LINE_NUMBER1 expanded)

    #define LINE_NUMBER2 400//#line LINE_NUMBER2 "file2.h"    //set next line number to 400 and current file name to "file2.h"

    #define FILE_NAME "file3.h"//#line 500 FILE_NAME    //set next line number to 500 and current file name to "file3.h"

    #define LINE_FILE 600 "test.h"//#line LINE_FILE    //set next line number to 600 and current file name to "test.h"

    arguments format#line 0    //error, the line number cannot less than 1#line 2147483648    //error, the line number cannot more than 2147483647#line +100    //error, the line number need not prefixed by '+' or '-'#line "file.h" 100    //error, the first argument shall be a number (after macro replacement)#line 100  L"file.h"    //error, the file name need not prefixed by 'L' (cannot be wide string literal)//#line 100  "file.h/"    //error, missing matched quotes, the /" is only a escape sequence

    counting of line number//#line 100    //set next line number to 100, but next broken '__LINE__' will expands to 101__LINE/__ ;

    Error directive------------------------------------------------------------------------------------------------------------------------------

    //#error    //stop preprocessing//#error message1    //stop preprocessing and output 'message1'

    expanded macro arguments#define MESSAGE2 message2//#error MESSAGE2    //macro expanded, stop preprocessing and output 'message2'

    #define MAX_VALUE 100//#error the "MAX_VALUE" cannot more than MAX_VALUE    //stop preprocessing and output 'the "MAX_VALUE" cannot more than 100'

    Pragma directive-----------------------------------------------------------------------------------------------------------------------------

    #pragma some_instructions    //valid, but all #pragma directives will be ignored and removed

    _Pragma operator (uncompleted)_Pragma ("string literal")    //it will regard as normal text

    [The End]


    最新回复(0)