Macro definition error in C? - c

#define SOUND_SPEED 0.034;
int rtt; //round trip time in microsecond
double distance;
distance = (double)(rtt*SOUND_SPEED)/2;
It complains error: expected expression before '/' token. Was is it bacause I can't use macro to define decimals or what?

Drop the semicolon:
#define SOUND_SPEED 0.034;
^
If you keep it the generated code will look like this:
distance = (double)(rtt*SOUND_SPEED;)/2;
^

#define SOUND_SPEED 0.034;
^
Do not use the trailing ;
Actually you should never terminate a macro with a ;:
PRE11-C. Do not conclude macro definitions with a semicolon
https://www.securecoding.cert.org/confluence/display/seccode/PRE11-C.+Do+not+conclude+macro+definitions+with+a+semicolon

You're using C, but you're trying to use a C++ style // comment. Depending on your compiler, that may not be allowed.
Edit: In fact, gcc -c89 -ansi gives that exact error message for a // comment and a totally different one for the extraneous ; in the define.

Related

How to properly define and use parameters in C macro functions?

I want to use a basic macro in C to access a certain Bit b in a char-Array (*char) Arr:
#define TstBit (Arr,b) ( Arr[b/8] & (1 << (b%8)) )
however upon usage like such:
int foo(const char *charArray) {
int readindex = 0;
[...]
if(TstBit(charArray,readIndex++)) {
I get an error on the line with the #define-Statement:
main.c | line 7 | error: 'Arr' undeclared (first use in this function)
I'm suspecting I'm either passing the arguments poorly when calling the Function or that the #define needs some more parentheses.
The space after TstBit seems to be the problem here. The pre-processor, unlike the C compiler, is a bit more fussy about spaces.
With your macro, what the pre-processor does is replace all occurrences of TstBit with (Arr,b) which is not your intention.
#define TstBit(Arr,b) ( Arr[b/8] & (1 << (b%8)) )
should work the way you want.
EDIT: Also note that there is a problem with the way you are trying to use this macro, as noted in this comment!
Macro arguments should ideally not have side-effects. If they do, you should take care that they do not lead to undefined or unintended behaviour.

How to fix `left hand operand has no effect` warning with variadic macro in C

I'm using the variadic macro to simulate a default argument. I compile with -Wunused-value. Thus, I get the following warning:
warning: left-hand operand of comma expression has no effect
Is there a way to somehow fix this warning without having to remove -Wunused-value? or do I have to end up using #pragma GCC diagnostic ignored "-Wunused-value"?
#include <stdio.h>
#define SUM(a,...) sum( a, (5, ##__VA_ARGS__) )
int sum (int a, int b)
{
return a + b;
}
int main()
{
printf("%d\n", SUM( 3, 7 ) );
printf("%d\n", SUM( 3 ) );
}
The ## construct that you are using is a gcc speciality and not portable. Don't use it, there are other ways.
The following should do what you expect
#define SUM2(A, B, ...) sum((A), (B))
#define SUM1(...) SUM2(__VA_ARGS__)
#define SUM(...) SUM1(__VA_ARGS__, 5, 0)
Such games with macro default arguments are frowned upon by many, because they may make the code more difficult to read.
For the moment I'd suggest that you don't use such constructs in your programs. You should perhaps learn more of the basics before you go into such esoteric stuff.
Also your idea to want to silence the compiler is really a bad one. The compiler is there to help you, listen to him. In the contrary, raise the warning level to a maximum and improve your code until it compiles without any warning.
Jens Gustedt proposed a very good problem-specific portable solution. I didn't know, ,##__VA_ARGS__ is a GCC extension (maybe Clang too?). There are however GCC-specific solutions for the authors initial intension.
As a problem-specific and very GCC-specific solution, you can use _Pragma("GCC diagnostic ignored \"-Wunused-value\"") and delimit it around the macro expansion. This will keep the comfort of readability. This does not work everywhere. It mainly fails within static initializer lists placed outside of functions where those pragmas can't be applied. I really was looking for a solution within such initializer lists because I couldn't find any which hides the warning pragmas from the reader. Other than that, for a function call like sum() for example - which I suppose to be only valid in a function body itself -, you can use it:
#define SUM(a,...) ({\
_Pragma("GCC diagnostic push")\
_Pragma("GCC diagnostic ignored \"-Wunused-value\"")\
sum( a, (5, ##__VA_ARGS__) );\
_Pragma("GCC diagnostic pop")\
})
Remember, you can only use it in function bodies and where an expression is expected. The warning will remain turned on after the macro expansion.
But I found a general solution! Conditional-macro-expansion is possible with the ,##__VA_ARGS__ feature. It gives you the power of conditional expansion based on blankness of the argument.
This feature does not necessarily add substitution power to the preprocessor. If you use arguments which include commas like (<...>) for false or 0 and (<...>,<...>) for true or 1, you can achieve the same. But only the conditional comma allows you the comfort of expanding conditionally based on the blankness of an argument.
See: you might be able to write your code like SUM(A) expanding to sum((A),5) without ##__VA_ARGS__ but you might not be able to write SUM(,B) expanding to sum((somevalue),B) . But you can do that with ##__VA_ARGS__ .
Example:
#define _VADIC(...) , ##__VA_ARGS__
//expands to A if A is not blank else to __VA_ARGS__ as fallback value
#define TRY(A,B) _TRY0(_VADIC(A), B)
#define _TRY0(...) _TRY1(__VA_ARGS__) /*expand before call*/
#define _TRY1(A, B, ...) B
//expands to THEN if A is blank otherwise expands to blank
#define IF(A,THEN) _IF0(_VADIC(A),THEN)
#define _IF0(...) _IF1(__VA_ARGS__) /*expand before call*/
#define _IF1(A,B,...) __VA_ARGS__
//expands to ELSE if A is not blank otherwise expands to blank
#define IFNOT(A,ELSE) _IFNOT0(_VADIC(A),,ELSE)
#define _IFNOT0(...) _IFNOT1(__VA_ARGS__) /*expand before call*/
#define _IFNOT1(A,B,C,...) C
#define IF_ELSE(A, THEN, ELSE) IF(A,THEN)IFNOT(A,ELSE)
Without the conditional comma, you only can expand conditionally on the number of arguments or on predefined concatenations but this way, you can use ANY single undefined symbol as condition.
PS: What about loops? Macros in C are designed to be finite for faster compilation. You won't get infinite loops since the limit of loop cycles depends on the source code size. Limited loops is the only thing which hinders you from turing-completeness, but practical real-world computer science problems (different from embedded or operating systems) don't need infinite loops for calculations. They are all limited depending with the problem size. The turing machine also uses a finite alphabet of symbols. You could know the limit of loop cycles which are needed in the worst case and it is possible to create a functional loop (a "reduce" or "filter" macro) running on variable-length macro argument lists which can reformat the macro argument list and do magic. The only requirement is the comma. You can't iterate over elements without a comma in between.

C Macro to prefix and suffix a string?

I'm trying to clean up my code for colouring strings. Here's what I have to prefix a red ANSI colour to a string, then suffix it with a reset colour.
#define GET_RED_TEXT(x) “\x1B[31m” x “\x1B[00m”
However, when I try use it...
src/util.c:18:15: error: expected expression
char *temp = GET_RED_TEXT("error: ");
^
includes/util.h:14:25: note: expanded from macro 'GET_RED_TEXT'
#define GET_RED_TEXT(x) “\x1B[31m” x “\x1B[00m”
^
src/util.c:22:14: error: expected ';' at end of declaration
va_end(arg);
^
;
Any ideas whats up with my macro?
Your macro has smart quotes in (“, ”) not real quotes (").
Also, as a matter of good practice, put a bracket round the definition, and x, e.g.:
#define GET_RED_TEXT(x) ("\x1B[31m" (x) "\x1B[00m")
You appear to have copied the code from some place and the double quotes are not valid try this
#define GET_RED_TEXT(x) "\x1B[31m" x "\x1B[00m"
copy and paste it into the editor please.
Note, that the your code is not highlighted properly.

Macro output explanation

When I run the following code,
#include<stdio.h>
#define X (4+Y)
#define Y (X+3)
int main()
{
printf("%d",4*X+2);
return 0;
}
I am getting the following output:
Error: Undefined symbol 'X'
Can someone please explain the output?
It is because the macro expects and argument since its defined with parentheses.
You would need to define it as
#define X 4+Y and #define Y X+3. Then you would run into another trouble because of cyclic definition in macros.
To be even more correct, as Drew suggested; when the example would be compilable when defining macros one usually puts the parentheses around expression to ensure expected operator precedence.
So your best shot would be:
#define X (4+Y)
#define Y (X+3)
Very close to your initial example, just a space character between name of a macro and its definition. However, it is still impossible to properly expand the macro due to the cyclic reference.
How to check what happened:
You can use gcc -E, which outputs a pre-processed file. It generates lots of output so I used tail. I also used 2>err to redirect error stream to a file, so the output is clear.
luk32:~/projects/tests$ gcc -E ./cyclic_macro_with_no_spaces.c 2> err | tail -n 6
int main()
{
printf("%d",4*X+2);
return 0;
}
luk32:~/projects/tests$ gcc -E ./cyclic_macro.c 2> err | tail -n 6
int main()
{
printf("%d",4*(4+(X+3))+2);
return 0;
}
In 1st example the X did not expand at all. While in the latter both macros got expanded, although only one. Giving the same output that Geoffrey presented in his answer.
Whether no space is a typo or not there is an undefined symbol 'X'. For different reason that are possible to trace by analyzing err files.
If the macros are left as invalid function-like macros, they are not getting expanded at all because you did not call it with parentheses. So X is never replaced with anything by the pre-processor, and is the reason for the Undefined symbol 'X' in your sample code.
If you wanted this to be expanded you would have to call it with parentheses like this:
printf("%d",4*X()+2);
This though would just error out when pre-processed as 4+Y and X+3 are not valid macro parameter names.
If your answer is corrected somewhat so that those defines are proper defines, and not function-like macros, ie:
#define X (4+Y)
#define Y (X+3)
You have a circular reference between the defines...
X -> Y -> X... etc.
Since it will only expand the macro once, it is getting expanded to
printf("%d",4*(4+(X+3))+2);
This explains why X is the undefined symbol in this use case.
You miss spaces
#define X (4+Y)
#define Y (X+3)

syntax error : missing ']' before ';' Array declaration error in C

i am writing in c, using Visual c++.
The compiler gives me the errors with the code below:
#define SIZE 3;
int myMatrix[SIZE][SIZE];
void funcMatrix(int M[SIZE][SIZE]);
The errors i get:
error C2143: syntax error : missing ']' before ';'
error C2059: syntax error : ']'
Ive tried declaring the constant differently, inside main and outside. It still doesn't work.
Would really appreciate it if someone can help me out...
You should use #define SIZE 3.
Preprocessor works as a raw string substitution, so with #define SIZE 3; your SIZE is replaced with 3; and you get:
int myMatrix[3;][3;];
void funcMatrix(int M[3;][3;]);
as a final result, hence the errors. This is a common error, then you get used to place ; at the end of C expression. However the preprocessor #define-s are not C code actually, but a simple (or not so simple) string processing operation which occurs before compilation.
In your code SIZE will be replaced by the define in this case 3; so you'll have
int myMatrix[3;][3;];
void funcMatrix(int M[3;][3;]);
Which causes a syntax error, so use #define SIZE 3 (without the ;) instead of #define SIZE 3;.
A #define NAME literally inserts whatever value comes after NAME.
Your macro expands to
int myMatrix[3;][3;];
Remove the ; in the macro definition.
you change :
#define SIZE 3;
to
#define SIZE 3
You need to remove the ; after the #define SIZE 3.
#defines don't require a semicolon
#define SIZE 3 not #define SIZE 3;
You can see what the compiler sees.
It can be a mess if you don't comment out included header files,
and I don't know how to do it in Visual C++,
but with GCC you run
gcc -E xx.c > xx.e
and you see what your code expands to after the #define's are processed.
There must be some way to do that with Visual C++ too.
Then you can still compile the .e file as c code.

Resources