|< C & C++ Preprocessor Directives 1 | Main | C & C++ Type Specifiers >| Site Index | Download |


 

 

 

 

 

MODULE 10

THE C/C++ PREPROCESSOR DIRECTIVES 2: #define etc.

 

 

 

 

 

My Training Period:        hours

 

The C/C++ preprocessor directives programming skills that should be acquired:

 

 

 

 

 

10.6    The #error And #pragma Preprocessor Directive

  • The #error directive takes the following form:

#error    tokens

  • It will prints an implementation-dependent message including the tokens specified in the directive.

  • The tokens are sequences of characters separated by spaces.  For example the following statement contains 6 tokens.

#error

  • In Borland C++, when an #error directive is processed, the tokens in the directive are displayed as an error message, preprocessing stops, and the program does not compile.  For example:

#if (MyVAL != 2 && MyVAL != 3)

#error    MyVAL must be defined to either 2 or 3

#endif

  • Then, when you compile the following simple program:

// the #error directive...

#include <stdio.h>

 

#if MyVAL != 2

#error MyVAL must be defined to 2

#endif

 

int main()

{

return 0;

}

// no output, error message during the compilation

  • The following error message should be generated.

Error:  test.cpp(7,1):Error directive: MyVAL must be defined to 2

  • In the real compilation the Output window is shown below for Visual C++ 2005 Express Edition.

The #error preprocessor directive use as seen in the Output window

// the #error directive...

#include <stdio.h>

 

#define MyVAL 2

#if MyVAL != 2

#error    MyVAL must be defined to 2

#endif

 

int main()

{

return 0;

}

// no output when running, no error when compiling

// another #error directive example

#include <stdio.h>

 

#if MyChar != 'X'

#error    The MyChar character is not 'X'

#endif

 

int main()

{

return 0;

}

// no output, with error message during the compilation

Error:  test.cpp(6, 1):Error directive: The MyChar character is not 'X'

#pragma    tokens

#pragma    message ("text" ["text"["text" ...]])

#pragma    message text

// the #pragma directive...

#include <stdio.h>

 

// displays either "You are compiling using

// version xxx of BC++" (where xxx is the version number)

// or "This compiler is not Borland C++", date, time

// console or not... by using several related

// predefined macro such as __DATE__ etc

 

#ifdef __BORLANDC__

#pragma message You are compiling using Borland C++ version __BORLANDC__.

#else

    #pragma message ("This compiler is not Borland C++")

#endif

#pragma message time: __TIME__.

#pragma message date: __DATE__.

#pragma message Console: __CONSOLE__.

 

int main()

{

return 0;

}

// no output

C C++ preprocessor directive pragmas program example

 

// #pragma directive...

#include <stdio.h>

 

// displays either "You are compiling using

// version xxx of BC++" (where xxx is the version number)

// or "This compiler is not Borland C++", date, time

// console or not... by using several related

// predefined macro such as __DATE__ etc

 

#ifdef __BORLANDC__

#pragma message You are compiling using Borland C++ version __BORLANDC__.

#else

#pragma message ("This compiler is not Borland C++")

#endif

#pragma message ("time:" __TIMESTAMP__)

#pragma message ("date:" __DATE__)

#pragma message ("file:" __FILE__)

 

int main()

{

return 0;

  }

 

C C++ preprocessor directive pragmas program example

// #pragma directives...

#include <stdio.h>

 

#if _M_IX86 != 500

    #pragma    message("Non Pentium processor build")

#endif

 

#if _M_IX86 == 600

    #pragma message("but Pentium II above processor build")

#endif

 

#pragma message("Compiling " __FILE__)

#pragma message("Last modified on " __TIMESTAMP__)

 

int main()

{

     return 0;

}

C C++ preprocessor directive pragmas program example

10.7    The # And ## Operators

#define    HELLO(x)    printf("Hello, "  #x  "\n");

printf("Hello,  " "John"  "\n");

printf("Hello, John\n");

#define    CAT(p, q)    p ## q

#include <stdio.h>

#define     HELLO(x)    printf("Hello, "  #x  "\n");

#define    SHOWFUNC(x)    Use ## Func ## x

 

int main(void)

{

      // new  concatenated identifier, UseFuncOne

      char * SHOWFUNC(One);

      // new  concatenated identifier, UseFuncTwo

      char * SHOWFUNC(Two);

     

      SHOWFUNC(One) = "New name, UseFuncOne";

      SHOWFUNC(Two) = "New name, UseFuncTwo";

     

     HELLO(Birch);

     printf("SHOWFUNC(One) -> %s \n",SHOWFUNC(One));

     printf("SHOWFUNC(One) -> %s \n",SHOWFUNC(Two));

    return 0;

}

 

Output:

 

 

 

 

 

 

 

 

 

 

 

-----------------------------------------------------------------------------------

 

C C++ preprocessor directive # and ## program example

 

10.8    Line Numbers

#line    100

#line    100    "file123.cpp"

10.9    Predefined Macros

Symbolic Constant

Explanation

__DATE__

The date the source file is compiled (a string of the form "mmm dd yyyy" such as "Jan 19 1999").

__LINE__

The line number of the current source code line (an integer constant).

__FILE__

The presumed names of the source file (a string).

__TIME__

The time the source file is compiled (a string literal of the form :hh:mm:ss).

__STDC__

The integer constant 1.  This is intended to indicate that the implementation is ANSI C compliant.

 

Table 10.1:  The predefined macros.

#include <iostream>

using namespace std;

 

int main(void)

{

   cout<<"Let test the free macros, standard and compiler specific..."<<endl;

   cout<<"\nPredefined macro __LINE__ : "<<__LINE__<<endl;

   cout<<"Predefined macro __FILE__ : "<<__FILE__<<endl;

   cout<<"Predefined macro __TIME__ : "<<__TIME__<<endl;

   cout<<"Predefined macro __DATE__ : "<<__DATE__<<endl;

   cout<<"Some compiler specific __MSDOS__: "<<__MSDOS__<<endl;

   cout<<"Some compiler specific __BORLANDC__: "<<__BORLANDC__<<endl;

   cout<<"Some compiler specific __BCPLUSPLUS__: "<<__BCPLUSPLUS__<<endl;

  

   return 0;

}

 

Output:

 

C C++ preprocessor directive predefined macros program example

 

10.10   Assertions

  • This is one of the macro used for simple exception handling.

  • The assert() macro, defined in the assert.h header file, tests the value of an expression.  If the value of the expression is 0 (false), then assert prints an error message and calls function abort() (of the general utilities library – stdlib.h) to terminate program execution.

  • This is a useful debugging tool, for example, testing if a variable has a correct value or not.  For example, suppose variable q should never be larger than 100 in a program.

  • An assertion may be used to test the value of q and print an error message if the value of q is incorrect.  The following statement would be:

assert(q <= 100);

  • If q is greater than 100 when the preceding statement is encountered in a program, an error messages containing the line number and file name is printed, and the program terminates.

  • The programmer may then concentrate on this area of the code to find the error.  If the symbolic constant NDEBUG (#define NDEBUG) is defined, that is no debugging, subsequent assertions will be ignored.

 

#define    NDEBUG

#include <stdio.h>

#include <assert.h>

#include <string.h>

#include <stdlib.h>

 

void TestString(char *string);

 

void main()

{

       // first test array of char, 10 characters...

       // should be OK for the 3 test conditions...

       char test1[ ] = "abcdefghij";

       // second test pointer to string, 9 characters...

       // should be OK for the 3 test conditions...

       char *test2  = "123456789";

       // third test array char, empty...

       // should fail on the 3rd condition, cannot be empty...

       char test3[ ] = "";

      

       printf("Testing the string #1 \"%s\"\n", test1);

       TestString(test1);

       printf("Testing the string #2 \"%s\"\n", test2);

       TestString(test2);

       printf("Testing the string #3 \"%s\"\n", test3);

       TestString(test3);

}

 

void TestString(char * string)

{

       // set the test conditions...

       // string must more than 8 characters...

       assert(strlen(string) > 8);

       // string cannot be NULL

       assert(string != NULL);

       // string cannot be empty....

       // test3 should fail here and program abort...

       assert(string != '\0');

}

 

Output:

 

C C++ preprocessor directive assert program example

C C++ using Borland Turbo debugger program example

 

Figure 10.1:  Borland Turbo® Debugger window.

 

// assert macro and DEBUG, NDEBUG

// NDEBUG will disable assert().

// DEBUG will enable assert().

#define DEBUG

#include <iostream>

   using namespace std;

#include <assert.h>

 

int main()

{

     int    x, y;

    

     // tell user if NDEBUG is defined and do assert.

     #if defined(NDEBUG)

     cout<<"NDEBUG is defined. Assert disabled,\n";

     #else

            cout<<"NDEBUG is not defined. Assert enabled.\n";

     #endif

    

     // prompt user some test data...

     cout<<"Insert two integers: ";

     cin>>x>>y;

     cout<<"Do the assert(x < y)\n";

    

     // if x < y, it is OK, else this program will terminate...

     assert(x < y);

     if(x<y)

     {

            cout<<"Assertion not invoked because "<<x<<" < "<<y<<endl;

            cout<<"Try key in x > y, assertion will be invoked!"<<endl;

     }

     else

            cout<<"Assertion invoked, program terminated!"<<endl;

     return 0;

}

 

Normal Output:

 

C C++ preprocessor directive DEBUG NDEBUG

 

Abnormal program termination output:

 

C C++ preprocessor directive DEBUG NDEBUG assert program example

C C++ preprocessor directive debug error Abort Retry Ignore

C C++ preprocessor directive assert program example

//////// testassert.cpp /////////

// DEBUG will enable assert().

#define DEBUG

#include <iostream>

#include <cassert>

using namespace std;

 

int main()

{

        int    x, y;

       

        // tell user if NDEBUG is defined and do assert.

        #if defined(NDEBUG)

                cout<<"NDEBUG is defined. Assert disabled,\n";

        #else

                cout<<"NDEBUG is not defined. Assert enabled.\n";

        #endif

       

        // prompt user some test data...

        cout<<"Insert two integers: ";

        cin>>x>>y;

        cout<<"Do the assert(x < y)\n";

       

        // if x < y, it is OK, else this program will terminate...

        assert(x < y);

        if(x<y)

        {

                cout<<"Assertion not invoked because "<<x<<" < "<<y<<endl;

                cout<<"Try key in x > y, assertion will be invoked!"<<endl;

        }

        else

                cout<<"Assertion invoked, program terminated!"<<endl;

        return 0;

}

 

[bodo@bakawali ~]$ g++ testassert.cpp -o testassert

[bodo@bakawali ~]$ ./testassert

 

NDEBUG is not defined. Assert enabled.

Insert two integers: 30 20

Do the assert(x < y)

testassert: testassert.cpp:24: int main(): Assertion `x < y' failed.

Aborted

 

[bodo@bakawali ~]$ ./testassert

 

NDEBUG is not defined. Assert enabled.

Insert two integers: 20 30

Do the assert(x < y)

Assertion not invoked because 20 < 30

Try key in x > y, assertion will be invoked!

 

----------------------------------------------------Note--------------------------------------------------

 

Program Sample

 

/*  assert.h

    assert macro

 */

 

/*

 *      C/C++ Run Time Library - Version 8.0

 *

 *      Copyright (c) 1987, 1997 by Borland International

 *      All Rights Reserved.

 *

 */

/* $Revision:   8.1  $ */

#if !defined(___DEFS_H)

#include <_defs.h>

#endif

 

#if !defined(RC_INVOKED)

 

#if defined(__STDC__)

#pragma warn -nak

#endif

#endif  /* !RC_INVOKED */

#if !defined(__FLAT__)

#ifdef __cplusplus

extern "C" {

#endif

 

void _Cdecl _FARFUNC __assertfail( char _FAR *__msg,

                                   char _FAR *__cond,

                                   char _FAR *__file,

                                   int __line);

 

#ifdef  __cplusplus

}

#endif

#undef assert

#ifdef NDEBUG

#  define assert(p)   ((void)0)

#else

#  if defined(_Windows) && !defined(__DPMI16__)

#    define _ENDL

#  else

#    define _ENDL "\n"

#  endif

#  define assert(p) ((p) ? (void)0 : (void) __assertfail( \

                    "Assertion failed: %s, file %s, line %d" _ENDL, \

                    #p, __FILE__, __LINE__ ) )

#endif

 

#else  /* defined __FLAT__ */

#ifdef __cplusplus

extern "C" {

#endif

 

void _RTLENTRY _EXPFUNC _assert(char * __cond, char * __file, int __line);

 

/* Obsolete interface: __msg should be "Assertion failed: %s, file %s, line %d"

 */

void _RTLENTRY _EXPFUNC __assertfail(char * __msg, char * __cond, char * __file, int __line);

 

#ifdef  __cplusplus

}

#endif

#undef assert

 

#ifdef NDEBUG

#define assert(p)   ((void)0)

#else

#define assert(p)   ((p) ? (void)0 : _assert(#p, __FILE__, __LINE__))

#endif

 

#endif  /* __FLAT__  */

#if !defined(RC_INVOKED)

#if defined(__STDC__)

#pragma warn .nak

#endif

 

#endif  /* !RC_INVOKED */

 

C & C++ programming tutorials

 

 

 

 

 

 

 

 

 

 

 

Further related preprocessor directives reading and digging:

 

  1. A complete process involved during the preprocessing, compiling and linking can be read in C/C++ - Compile, link and running programs.
  2. Check the best selling C / C++ books at Amazon.com.

 

 

 

 

 

 

|< C & C++ Preprocessor Directives 1 | Main | C & C++ Type Specifiers >| Site Index | Download |


C & C++ Preprocessor Directives:  Part 1 | Part 2 |