Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

The GNU C Programming Tutorial - Extended macro example

Node:Extended macro example, Next:, Previous:Macros, Up:Preprocessor directives



Extended macro example

Here are some examples of macros taken from actual working C code, in this case the code of GNU Emacs, the text editor of choice for many C programmers, and in fact the editor in which this edition of the book was written.

Most of the macro examples below define various types of integer as having certain sizes. It can be very useful when doing advanced C programming to know whether a long integer, for instance, is 32 or 64 bits long on your system; if you select the wrong size, your code might crash or might not even compile. In the case of Emacs, the maximum size of certain variables (how many bits they contain) affects every aspect of its operation, even determining how long an Emacs text file can be.

Each piece of code below is prefixed with the name of the file from which the code is taken, and followed by a note on some interesting features of the macros defined.

  • emacs/src/config.h
    /* Note that lisp.h uses this in a preprocessor conditional, so it
       would not work to use sizeof.  That being so, we do all of them
       without sizeof, for uniformity's sake.  */
    #ifndef BITS_PER_INT
    #define BITS_PER_INT 32
    #endif
    
    #ifndef BITS_PER_LONG
    #ifdef _LP64
    #define BITS_PER_LONG 64
    #else
    #define BITS_PER_LONG 32
    #endif
    #endif
    

    In the middle of this set of macros, from config.h, the Emacs programmer used the characters /* and */ to create an ordinary C comment. C comments can be interspersed with macros freely.

    The macro BITS_PER_INT is defined here to be 32 (but only if it is not already defined, thanks to the #ifndef directive). The Emacs code will then treat integers as having 32 bits. (See Integer variables.)

    The second chunk of macro code in this example checks to see whether BITS_PER_LONG is defined. If it is not, but _LP64 is defined, it defines BITS_PER_LONG to be 64, so that all long integers will be treated as having 64 bits. (_LP64 is a GCC macro that is defined on 64-bit systems. It stands for "longs and pointers are 64 bits".) If _LP64 is not present, the code assumes it is on a 32-bit system and defines BITS_PER_LONG to be 32.

  • emacs/src/lisp.h
    /* These are default choices for the types to use.  */
    #ifdef _LP64
    #ifndef EMACS_INT
    #define EMACS_INT long
    #define BITS_PER_EMACS_INT BITS_PER_LONG
    #endif
    #ifndef EMACS_UINT
    #define EMACS_UINT unsigned long
    #endif
    #else /* not _LP64 */
    #ifndef EMACS_INT
    #define EMACS_INT int
    #define BITS_PER_EMACS_INT BITS_PER_INT
    #endif
    #ifndef EMACS_UINT
    #define EMACS_UINT unsigned int
    #endif
    #endif
    

    This set of macros, from lisp.h, again checks to see whether _LP64 is defined. If it is, it defines EMACS_INT as long (if it is not already defined), and BITS_PER_EMACS_INT to be the same as BITS_PER_LONG, which was defined in config.h, above. It then defines EMACS_UINT to be an unsigned long, if it is not already defined.

    If _LP64 is not defined, it is assumed we are on a 32-bit system. EMACS_INT is defined to be an int if it is not already defined, and EMACS_UINT is defined to be an unsigned int if it is not already defined.

    Again, note that the programmer has freely interspersed a comment with the preprocessor code.

  • emacs/src/lisp.h
    /* These values are overridden by the m- file on some machines.  */
    #ifndef VALBITS
    #define VALBITS (BITS_PER_EMACS_INT - 4)
    #endif
    

    Here is another example from lisp.h. The macro VALBITS, which defines another size of integer internal to Emacs, is defined as four less than BITS_PER_EMACS_INT -- that is, 60 on 64-bit systems, and 28 on 32-bit systems.

  • emacs/src/lisp.h
    #ifndef XINT   /* Some machines need to do this differently.  */
    #define XINT(a) ((EMACS_INT) (((a) << (BITS_PER_EMACS_INT - VALBITS)) \
                                       >> (BITS_PER_EMACS_INT - VALBITS)))
    #endif
    

    The interesting feature of the XINT macro above is not only that it is a function, but that it is broken across multiple lines with the backslash character (\). The GCC preprocessor simply deletes the backslash, deletes the preceding whitespace from the next line, and appends it where the backslash was. In this way, it is possible to treat long, multi-line macros as though they are actually on a single line. (See Advanced operators, for more information on the the advanced operators << and >>.)

 
 
  Published under free license. Design by Interspire