Preprocessor – the #line Directive

I don’t think I have ever seen this directive used.

Behaviour of this preprocessor directive is the same for both C and C++ compilers.

Purpose

The #line directive allows setting the current line number and name of the file being compiled.

Format

#line integer

or

#line integer "file_name"

or

#line preprocessing_expression

All preprocessor directives begin with the # symbol. It must be the first character on the line or the first character on the line following optional white space.

Some early compilers flagged an error if # was not the first character on the line.

Spaces or tabs are permitted between the # and line, but not escape characters or other symbols or macros. The preprocessor removes white space and concatenates the # and line together.

If anything follows the #line directive (other than white space) then the program is malformed.

The following are valid uses:

#line 100
# line   100
# /* comments are white space */ line 100

The following are invalid uses:

// #\ is not a valid preprocessor directive
# \t line 100
// #" is not a valid preprocessor directive
# "" line 100

Use

There are three different forms of the #line directive which allow you to change the current line numbering and file name during preprocessing.

First Form – #line integer

When the line number is changed, the line immediately following the #line directive receives the new line number:

#line 123
/* this line is now line number 123 */
/* this line is line number 124 */
/* this line is line number 126 */

For C89/C90 and C++97, the valid range of values for the line number is from 1 to 32767 (0x0001 to 0x7FFF).

In C99 and the upcoming C++0x, the valid range of values for the line number is from 1 to 2147483648 (0x00000001 to 0x7FFFFFFF).

How the compiler deals with out of range values is undefined. Some compilers may accept them, others may issue a warning or error.

Second Form – #line integer file_name

When file_name is specified, the working name of the file being compiled is changed to the specified string. The file_name must be enclosed by double quotes (").

In the following example, the line number remains the same but the name of the file being compiled is changed to new_file_name.abc. Only the name the compiler thinks it is compiling changes (and which it will return using the __FILE__ macro), the actual (physical) file name remains the same:

#line __LINE__ "new_file_name.abc"

Third Form – #line preprocessor_tokens

The final form of the #line directive allows you to specify preprocessor tokens to be expanded. After expansion, the third form must look like one of the first two forms. If it does not, the program is malformed. NOTE: the preprocessor tokens are expanded, but not evaluated.

#define LINE_NUMBER 100

#define FILE_NAME(f) #f

#line LINE_NUMBER FILE_NAME(abc.h)

In the above example, LINE_NUMBER is expanded to 100 and FILE_NAME stringizes the passed parameter.

After compilation, the next line will be line number 100 and the name of the file being compiled will be abc.h.

NOTE: changing the line numbers and file names can cause grief when you try to debug your code.

Changing line numbers and the working file name can make debugging much harder.

When I used GCC to test the code, the debug information contained line numbering information and file name information that was different from what the IDE (in this case Code::Blocks) knew it to be. When I set breakpoints, Code::Blocks used the line and file name information it was aware of – which was different from what ended up in the debug information. I had to set the breakpoints manually for the “correct” line numbers and file name.

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *