4

I've been working on a piece of code that had an overlooked derp in it:

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>

#define MAX_N_LENGTH 

/*function prototypes*/

int main(){
...
}

It should be easy to spot with the context removed: #define MAX_N_LENGTH should have read #define MAX_N_LENGTH 9. I have no idea where that trailing constant went.

Since that macro was only used in one place in the form of char buf[ MAX_N_LENGTH + 1], it was extremely difficult to track down and debug the program.

Is there a way to catch errors like this one using the gcc compiler?

4
  • 2
    Please avoid answering the question in comments. Commented Sep 5, 2016 at 17:33
  • char buf[ MAX_N_LENGTH + 1] is expanded as char buf[+1], this is valid and gcc doesn't warn about valid code. Commented Sep 5, 2016 at 17:36
  • Please change question name to How to catch defined empty preprocessor macro with gcc? or something. Commented Feb 1, 2019 at 9:11
  • 1
    Side note for anyone ending up here like me who actually wants to find undefined macros in #if directives (where they are silently replaced by 0): In GCC, use -Wundef (gcc.gnu.org/onlinedocs/gcc/Warning-Options.html and stackoverflow.com/a/54477120/1306747) Commented Dec 11, 2020 at 13:15

4 Answers 4

3

You can use char buf[1 + MAX_N_LENGTH], because char buf[1 +] should not compile with the error message error: expected expression before ']' token:

http://ideone.com/5m2LYw

Sign up to request clarification or add additional context in comments.

2 Comments

You mean char buf[MAX_N_LENGTH + 1]
@AlterMann no, char buf[+1] compiles, while char buf[1+] does not compile.
2

What you have there isn't an undefined macro. It's an empty macro. And defined empty macros are perfectly legit, because you can test for their definedness.

They're used quite a lot in the implementation header files, although all those empty macros will be in the implementation namespace, which means they will either contain two underscores or an underscore followed by an uppercase letter.

What you could do is test whether you have an empty macro that's not in the implementation namespace, and you can do that with:

cpp -dM YOUR_FILE.c |
     cut -d\  -f2- | grep '^[a-zA-Z0-9_]* $' |grep -v -e __ -e ^_[A-Z]

For your example, it should output just MAX_N_LENGTH.

Comments

1

It's not possible to catch this error in the general sense, because it isn't an error. There's plenty of cases where this sort of behavior is desired, so the compiler cannot treat it as an error or a warning.

If you can track the error down to a line, using gcc's -E command line argument will cause it to output the result of the preprocessor. In that case, your char line would have turned to char buf[+1], which is legal C code, but might catch your attention because you expected it to be char buf[9+1]. -E causes gcc to print those results, so you would actually see char buf[+1] in the output of gcc.

Issues like this are why C++ discourages use of define macros in this way (C++, of course, has more alternatives than C which makes it easier to discourage them)

1 Comment

Future Googlers: also see PSkocik's answer here; I could only accept one but they're both excellent.
1

You can use the preprocessor to catch when a macro is either 0 or defined without a value:

#define VAR

#if VAR+0 == 0
#error "VAR is either 0 or defined without a value."
#endif

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.