I am trying to port some relatively modern C code to an older compiler.
This compiler (DICE), it seems, chokes on the first header file and the first occurrence of this idiom:
#ifndef SOMETHING
#define SOMETHING
...
#endif /* SOMETHING */
it dies on the second line in the header with:
DCPP: "../../code/someheader.h" L:2 C:0 Error:39 Syntax Error
Changing to #define SOMETHING 1 made no difference.
So I have really two questions, am I using DICE with the wrong option or something, or did C programmers use some other idiom equal to ifndef-define back in the old days?
References:
DICE Wikipedia Entry
Original source code, runs on Unix
Slightly updated Amiga version
The author of DICE, Matt Dillon, went on to produce DragonFlyBSD
If it is this C compiler then by looking at the sources (src\dcpp\cpp.c) you can see that newlines only include the carriage return character and not the linefeed character.
If you have a line ending with CRLF then when the compiler strips the whitespace at the start of the line, it does not strip the linefeed before the # which is a syntax error, since preprocessor directives starting with # must be the first non-whitespace character in the line.
#if SOMETHING
#else
#endif
might just work everywhere
Related
I'm trying to get a bunch of C modules written in 1994 for a Panasonic 3DO lib to compile with armcc. I've run into an error which I'm kind of confused about. My knowledge of C is not that deep, so perhaps one of you would be so kind as to help me figure this out:
#define DS_MSG_HEADER \
long whatToDo; /* opcode determining msg contents */ \
Item msgItem; /* message item for sending this buffer */ \
void* privatePtr; /* ptr to sender's private data */ \
void* link /* user defined -- for linking msg into lists */
The \ character is used in many include files in this library I'm unfamiliar with this syntax... and the ARM compiler seems to hate it.
Serious error: misplaced preprocessor character '\'
If you know why these \ characters are being used, could please explain? (Sorry if its a noob question) Also, is there an alternative way to write this so the compiler is happy?
This error is shown (among other reasons) if the shown backslash '\' is not the last character on the line.
I can think of two reasons:
Somehow you got at least one whitespace (space, tab) after the backslash.
I never had this problem.
The source is stored with Windows-style end-of-line markers, that are '\r' and '\n', "carriage return" and "line feed". And you are trying to compile it on a Unix-like system (Linux?) or by a compiler that expects Unix-like end-of-line markers, that is only '\n', "line feed". (Or the other way around.)
This is a quite common problem, that hits me time after time.
In any case, open the source in a capable editor and enable the visibility of "unvisible characters", commonly an option with this icon: ΒΆ. Check for whitespace. Then check for the coding of the end-of-line. Save with the appropriate one.
I'm going through some C course notes, and every C program source file begins with a single # on the first line of the program.
Then there are blank lines, and following that other stuff followed by the main function.
What is the reason for the #?
(It's out of term now and I can't really ask the chap.)
Here's an example:
#
#include <stdio.h>
int main() {
printf("Hello, World!");
return 0;
}
Wow, this requirement goes way back to the 1970s.
In the very early days of pre-standardised C, if you wanted to invoke the preprocessor, then you had to write a # as the first thing in the first line of a source file. Writing only a # at the top of the file affords flexibility in the placement of the other preprocessor directives.
From an original C draft by the great Dennis Ritchie himself:
12. Compiler control lines
[...] In order to cause [the] preprocessor to be invoked, it is necessary that the very
first line of the program begin with #. Since null lines are ignored by the preprocessor, this line need contain no other
information.
That document makes for great reading (and allowed me to jump on this question like a mad cat).
I suspect it's the lecturer simply being sentimental - it hasn't been required certainly since ANSI C.
It Does Nothing
As of the ISO standard of C/C++:
A preprocessing directive of the form
# new-line
has no effect.
So in today's compilers, that empty hash does not do anything (like- new-line ; has no functionality).
PS: In * pre-standardized C*, # new-line had an important role, it was used to invoke the C Pre-Processor (as pointed out by #Bathsheba). So, the code here was either written within that time period, or came from the habit of the programmer.
Edit: recently I have come across code like this-
#ifdef ANDROID
#
#define DEVICE_TAG "ANDROID"
#define DEBUG_ENABLED
#
#else
#
#define DEVICE_TAG "NOT_ANDROID"
#
#endif /* ANDROID */
Here, those empty hashes are there only for making the code look good. It also improves readability by indicating that it is a preprocessor block.
You need to know about the Compilation process of C. Because that is "must know" how the Source code converting into Executable binary code (file).
From the Compilation Process, the C source code has to Cross the pre-processor Section. But how to tell the Compiler to pre-process the code?... That the time # Symbol was introduced to the indicator of Preprocess to the compiler.
For Example #define PI 3.141 is in the Source code. Then it will be change after the Preprocessing session. Means, all the PI will be changed into 3.141.
This like #include <stdio.h>, the standard I/O Functions will be added into your Source code.
If you have a Linux machine, compile like gcc -save-temps source_code.c. And see the compiler outputs.
I am testing two versions of the same code (with GCC version 4.9.2 on Linux, no parameters).
Both have a #define directive, followed by an #ifdef/#endif pair further down.
Now, it turns out that the combination works properly only if the label after the initial #define starts with an underscore. Without the underscore, it works.... in a very weird way, only every third time.
In other words, this works
#define _whatever
while this doesn't:
#define whatever
Even though I know how to make the directive work, just curious - does that behavior follow any standard?
Edit:
Following requests below, here's two absolutely real examples.
This one prints the line "Preprocessor works":
#define _whatever
#include <stdio.h>
void main()
{
#ifdef _whatever
printf("Preprocessor works \n");
#endif
}
... and this one doesn't output anything:
#define whatever
#include <stdio.h>
void main()
{
#ifdef whatever
printf("Preprocessor works \n");
#endif
}
Yes, I am even using the word "whatever" literally - I don't think, it is defined anywhere else. But again, it's the underscore that makes the label work.
There is absolutely no requirement, in any known version of gcc, that preprocessor macros begin with an underscore.
As a general rule, preprocessor macros that begin with various combinations of underscores are reserved to the implementation, and users are advised to ignore them. So #define whatever and #ifdef whatever absolutely must work.
I agree that this is a baffling and frustrating problem. There's something strange going on, but whatever the explanation is, it's not that gcc is requiring leading underscores.
Ok, so the answer is - my sloppy command of the tools.
Specifically:
(1) I was using a header file to add/remove the #define directive
(2) I have (mindlessly) compiled the header by using "gcc *" in place of "gcc *.c"
(3) The occasional presence of the compiled *.h.gch file explains the results.
So, what seemed like erratic behavior was actually me (mindlessly) removing the *.h.gch from time to time.
Thanks everyone - I have learned a lot from all the replies.
As far as I know \ in C just appends the next line as if there was not a line break.
Consider the following code:
main(){\
return 0;
}
When I saw the pre-processed code(gcc -E) it shows
main(){return
0;
}
and not
main(){return 0;
}
What is the reason for this kind of behaviour? Also, how can I get the code I expected?
Yes, your expected result is the one required by the C and C++ standards. The backslash simply escapes the newline, i.e. the backslash-newline sequence is deleted.
GCC 4.2.1 from my OS X installation gives the expected result, as does Clang. Furthermore, adding a #define to the beginning and testing with
#define main(){\
return 0;
}
main()
yields the correct result
}
{return 0;
Perhaps gcc -E does some extra processing after preprocessing and before outputting it. In any case, the line break seen by the rest of the preprocessor seems to be in the right place. So it's a cosmetic bug.
UPDATE: According to the GCC FAQ, -E (or the default setting of the cpp command) attempts to put output tokens in roughly the same visual location as input tokens. To get "raw" output, specify -P as well. This fixes the observed issues.
Probably what happened:
In preserving visual appearance, tokens not separated by spaces are kept together.
Line splicing happens before spaces are identified for the above.
The { and return tokens are grouped into the same visual block.
0 follows a space and its location on the next line is duly noted.
PLUG: If this is really important to you, I have implemented my own preprocessor with correct implementation of both raw-preprocessed and whitespace-preserving "pretty" modes. Following this discussion I added line splices to the preserved whitespace. It's not really intended as a standalone tool, though. It's a testbed for a compiler framework which happens to be a fully compliant C++11 preprocessor library, which happens to have a miniature command-line driver. (The error messages are on par with GCC, or Clang, sans color, though.)
From K&R section A.12 Preprocessing:
A.12.2 Line Splicing
Lines that end with the backslash character \ are
folded by deleting the backslash and the following newline character.
This occurs before division into tokens.
It doesn't matter :/ The tokenizer will not see any difference. 1
Update In response to the comments:
There seems to be a fair amount of confusion as to what the expected output of the preprocessor should be. My point is that the expectation /seems/ reasonable at a glance but doesn't actually need to be specified in this way for the output to be valid. The amount of whitespace present in the output is simply irrelevant to the parser. What matters is that the preprocessor should treat the continued line as one line while interpreting it.
In other words: the preprocessor is not a text transformation tool, it's a token manipulation tool.
If it matters to you, you're probably
using the preprocessor for for something other than C/C++
treating C++ code as text, which is a ... code smell. (libclang and various less complete parser libraries come to mind).
1 (The preprocessor is free to achieve the specified result in whichever way it sees fit. The result you are seeing is possibly the most efficient way the implementors have found to implement this particular transformation)
I added this in my code:
#ifdef DEBUG_MODE
printf("i=%d\n",i);
fflush(stdout);
#endif
and my question is, if I'm not in DEBUG_MODE what the compiler does when compiling this?
The compiler will do nothing, because there will be nothing there when DEBUG_MODE is not defined.
#ifdef and #endif control conditional compilation. This happens during an initial pass over the program, making dumb textual substitutions before the compiler even begins to consider the file to contain C code specifically. In this case, without the symbol defined only whitespace is left. The text is never even lexed into C tokens if the preprocessor define tested for isn't defined at that point.
You can see this for yourself: just invoke your compiler with whatever flag it uses to stop after preprocessing - e.g. gcc -E x.cc - and at that point in the output there will just be an empty line or two. This is also a very important technique for understanding macros, and a good thing to do when you just can't guess why some program's not working the way you expect - the compiler says some class or function doesn't exist and you've included its header - look at the preprocessed output to know what your compiler is really dealing with.
if DEBUG_MODE is not defined, the code under it will not be compiled.