I wrote the following C code (according to the C99 standard) and it ran with no problems:
#include <stdio.h>
#ifdef _WIN32
printf("Running on Windows");
#endif
void test(int x);
int main() {
return 0;
}
but adding else caused so much errors (around 12) what's the problem with the new code:
#ifdef _WIN32
printf("Running on Windows");
#else
printf("Running on Windows");
#endif
Some of the errors:
error: expected parameter declarator
expected ')'
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
error: conflicting types for 'printf'
When you use conditional compilation the preprocessor adds code to your program before the compile step.
So, if the symbol _WIN32 exists, then you are effectively saying
printf("Running on Windows");
void test(int x);
int main() {
return 0;
}
and that is syntactically incorrect because you have executable code (a call to printf) outside all functions.
If you didn't have a problem before you added the '#else' then that was because the symbol _WIN32 doesn't exist and the preprocessor wasn't adding the printf statement to your code.
Related
Given the following code written according to the C99 standard:
#define LOW 1
#define MEDIUM 2
#define HIGH 3
#define LOGGING_LEVEL HIGH
#if LOGGING_LEVEL >= MEDIUM
#define LOG_MEDIUM(message) printf(message)
#else
#define LOG_MEDIUM(message) ((void)0)
#endif
void load_configuration() {
//...
LOG_MEDIUM("Configuration loaded\n");
}
what's the purpose of ((void)0) I searched the web a lot but nothing found regarding this.
Plus, why didn't we wrote ; after using printf(message)
The void-cast fixes a compiler warning. Here's an analogous testcase:
int main(void)
{
0; // generates "foo.c:3:2: warning: statement with no effect"
(void)0;
return 0;
}
and (using a script to add gcc's warning flags) you see a warning for the line without a cast:
$ gcc-stricter -c foo.c
foo.c: In function ‘main’:
foo.c:3:2: warning: statement with no effect [-Wunused-value]
0;
^
The extra parentheses and lack of semicolon allow the macro's result to be used interchangeably with the printf.
Main idea is to exclude all LOG_MEDIUM if the criteria was not meet.
After compilation those calls will not affect functionality.
I have a simple log macro, this is the .h file :
#ifndef __LOGGER_H
#define __LOGGER_H
#define LOG_ERROR(errorMsg) logError(__FILE__, __LINE__, errorMsg)
#endif
...and this is the .c file :
#include <stdio.h>
#include "Logger.h"
void logError(const char* filename, int line, const char* errorMsg)
{
printf("[File : %s] - [Line: %d} - [Error Message : %s]\n", filename, line, errorMsg);
}
When I use the macro in a .c file :
#include <Common/Logger.h>
void func(int index, int value)
{
if (IsIndexOutOfRange(index, NUMBER_OF_PARAMS))
{
LOG_ERROR("Index out of range!");
return;
}
.
.
.
}
...and build (vs2013) I get :
warning C4013: 'logError' undefined; assuming extern returning int
Warning C4013 usually means that you forgot to include the correct library or need to use extern. I suspect I need extern somehow, but do not know how to fix this with a macro.
How do I solve this?
If I define
#if SOMETHING
#endif
and I have not defined SOMETHING anywhere. Would the code inside #if compile ?
When the name used in the argument expression of #if is not defined as a macro (after all other macro replacement is finished), it is replaced with 0. This means that your #if SOMETHING will be interpreted as #if 0. The code under #if will be removed by preprocessor.
The rule applies to more complex expressions as well. You can do
#define A 42
#if A + B
which will evaluate to #if 42, since unknown name B is interpreted as 0
No, as long as SOMETHING is also not one of the predfined macros or a macro passed on the commandline to the compiler.
I think in C99 it defaults to 0 while in C89 it does not as here its giving me an error
Source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define A 42
#define B
int main(int argc, char *argv[]){
int c;
#if A
c = A + B;
#endif
printf("%d\n",c);
return 0;
}
Error :
error: expected expression before ‘;’ token
No, because as an undefined macro, it would not necessarily be replaced with anything... but that is probably compiler specifc, and not to be trusted.
You may want to use:
#ifdef DEFINED_WORD
#ifndef DEFINED_WORD
Where DEFINED_WORD is declared by a #define, like: #define DEFINED_WORD. The ifdef construct ONLY compiles the code between that and the #endif if DEFINED_WORD was defined. The opposite is true of #ifndef. You can nest them like so:
#ifdef DEFINED_WORD
printf ( "DEFINED_WORD is defined\n" );
#ifndef DEFINED_WORD
printf ( "This line will NEVER print\n" );
#endif
printf ( "This line will print if DEFINED_WORD is defined\n" );
#endif
printf ( "This line will ALWAYS print.\n" );
In my code, I have constructs like:
#ifdef DEBUG
printf ( "array[%d] = %d\n", i, array[i] );
#endif
To deactivate all of the DEBUG code, just comment out the line that you MUST have before calling that #ifdef (top of the source file, or in an included header which you included at the top of the source file, in good form). #define DEBUG
Hope that helps.
// screen.h
#ifndef screen_h
#define screen_h
#define MAC 1
#define WIN 2
#define LNX 3
#ifdef PLATFORM
# undef PLATFORM
#endif
#define PLATFORM MAC
void screen_init();
#endif
// screen.c
#include <string.h>
#include <stdlib.h>
#include "screen.h"
#if PLATFORM == MAC
#include <curses.h>
void screen_init(){
erase();
}
#endif
I don't understand why it is not seeing my prototype in screen.h
Any suggestions/hints are appreciated!
ISO/IEC 9899:TC2 - 6.2.1.2:
A function prototype is a declaration of a function that declares the types of its parameters.
An empty argument list in a function declaration indicates that the number and type of parameters is not known. You must explicitly indicate that the function takes no arguments by using the void keyword. Otherwise your function declaration does not count as a valid prototype.
void screen_init(void);
I met this similar error minutes ago. After i'd added the relatived function declaration in head file, error's gone.
Also, some said that canceling the compile option '-Wmissing-prototypes' should work, but i didn't have tried that. Good luck.
I just had this problem today.
I defined a function that just used internally
void func(void) {
}
int main(void) {
func();
}
This will give me that warning.
I had to add the prototype at the beginning of the file to get rid of the warning.
void func(void);
void func(void) {
}
int main(void) {
func();
}
#include <stdio.h>
#define main() main(){printf("hi");}int i()
main()
{//empty main
}
what is the use of int i()
That's a pretty silly program, but the purpose of the int i() is so that it will compile - the braces at the end:
{//empty main
}
will cause an error if there isn't a function declaration included in the #define statement. If I delete it, gcc gives the error:
testfile.c:4: error: expected identifier or ‘(’ before ‘{’ token
You can use the -E flag to gcc to see why the int i() is necessary - it will show you the output of the preprocessor without compiling.
Think about what you get if you expand the macro main() in the program:
#include <stdio.h>
main(){printf("hi");}int i()
{//empty main
}
The int i() is needed there to make the remaining { ... } part of a syntactically valid function definition.
As for intention, I can only guess that the point of the macro is to replace the existing main with a stub one. It's a bit icky IMO.
In that code main() will be expanded and the result will end with
int i()
{//empty main
}
what is the use of int i()
It makes the output of a very strange and broken macro compilable