What error is thrown when macro and function conflict in C arises?
Is it a macro processor error or does this error occur due to some language violation?
For example, in this code:
#include <stdio.h>
#define MAX(i, j) (i>j)? i : j
int MAX(int i, int j){
return (i>j) ? i : j;
}
int main(){
int max = MAX(5, 7);
printf("%d",max);
return 0;
}
The program throws a compile time error. But I don't understand whether it was some language violation or macro expansion error or something else.
During the preprocessing phase the code gets converted to :
int (int i>int j)? int i : int j{
return (i>j) ? i : j;
}
int main(){
int max = (5>7)? 5 : 7;
printf("%d",max);
return 0;
}
...which, as anyone can tell, is an illegal C code.
(With gcc you could use an -E option to see the preprocessed version of the file.)
Others have pointed out the problem but gave no solutions. The best would be to just use MAX as an inline function. If the macro is in a header, put the inline function definition in the header instead. If you still wish to use a macro (or using an old C compiler which doesn't support inline functions) you can define the function this way:
int (MAX)(int i, int j){
return (i>j) ? i : j;
}
This will prevent the troubling macro expansion and provide MAX as an external function. This will enable you to, for example, assign its address to a variable.
extern int (MAX)(int, int);
...
int (*max_func_ptr)(int, int);
...
max_func_ptr = MAX;
You'll get a compiler error because the macro will be expanded before compilation is attempted.
This is a really nasty problem, and one for which there is not really a solution. For this reason you should avoid defining un-scoped, function-like macros as much as possible, especially in headers that are widely included. Like everything, they have their place, but you need to be careful not to overuse them.
There is no error that occurs specifically to call out that there's a conflict. What happens is that the macro processing occurs first, so in a sense macro definitions respect no name spaces - this is one of the main reasons why macros considered bad form and should be avoided except as a last resort. See this question for an example of a situation where someone's perfectly valid use of the name BitTest for a template was screwed over because someone else decided to create a macro using that name to 'alias' another name: Win32: BitTest, BitTestAndComplement, ... <- How to disable this junk?
So in your example, as other answers have mentioned, once the preprocessing step has occurred, you'll end up with something like the following snippet being passed to the C compiler in place of your function definition:
int (int i>int j)? int i : int j{
return (i>j) ? i : j;
}
This isn't valid C, so you'll get a compiler error that might say (from GCC 3.4.5):
error: syntax error before "int"
or (from MSVC 9):
error C2059: syntax error : 'type'
Which really isn't much help, because when you look at the line the error is refering to in your editor, it'll still look like:
int MAX(int i, int j){
which looks valid.
There are several techniques that are used to help avoid the problem:
use all caps for macro names and only macro names; this is a convention that is largely followed to keep the macro namespace separate from names used for other things
put parens around names that you don't want expanded as macros (this only works for 'function-like' macros). If your example had been written as follows:
int (MAX)(int i, int j){
return (i>j) ? i : j;
}
it would not have resulted in the macro expansion. However, I don't see people doing this very often. One set of utility routines I have uses this technique to protect against macro name collisions, and I often get questions about why all the function names are in parens. Also several editors get confused with function navigation for those files.
avoid using macros; as I mentioned this is one reason that macros are considered bad form. There are other reasons including that they can easily cause the expanded form to produce bad or unexpected expressions if you don't properly use parens around macro parameters or by evaluating a macro parameter that has side effects more than once.
Use inline functions or function templates instead if you can.
As preprocessor macros are only used for processing plain text, these conflicts would always cause a compile time error.
The pre-processing occurs first, so line 4 will become:
int (int i>int j)? int i : int j
which is not valid C.
Related
Since I found this particular documentation on https://www.tutorialspoint.com/c_standard_library/c_function_rand.htm,I have been thinking about this particular line of code srand((unsigned)time(&t));.Whenever I had to generate some stuff,I used srand(time(NULL)) in order not to generate the same stuff everytime I run the program,but when I came across this,I have been wondering :Is there any difference between srand((unsigned)time(&t)) and srand(time(NULL))?Because to me they seem like they do the same thing.Why is a time_t variable used?And why is the adress operator used in srand()?
#include <stdio.h>
#include<stdlib.h>
int main(){
int i,n;
time_t t;
n = 5;
srand((unsigned)time(&t));
for (i = 0; i < n; i++) {
printf("%d\n", rand() % 50);
}
return(0);
}
Yes, it will yield the same result. But the example is badly written.
I would be careful reading Tutorialspoint. It's a site known for bad C code, and many bad habits you see in questions here at SO can be traced to that site. Ok, it's anecdotal evidence, but I did ask a user here why they cast the result of malloc, and they responded that they had learned that on Tutorialspoint. You can actually see (at least) four examples in this short snippet.
They cast the result from the call to time() which is completely unnecessary and just clutters the code.
For some reason they use the variable t, which is completely useless in this example. If you read the documentation for time() you'll see that just passing NULL is perfectly adequate in this example.
Why use the variable n? For this short example it's perfectly ok with a hardcoded value. And when you use variables to avoid hardcoded values, you should declare them const and give them a much more descriptive name than n. (Ok, I realize I was a bit on the edge when writing this. Omitting const isn't that big of a deal, even if it's preferable. And "n" is a common name meaning "number of iterations". And using a variable instead of a hard coded value is in general a good thing. )
Omitted #include<time.h> which would be ok if they also omitted the rest of the includes.
Using int main() instead of int main(void).
For 5, I'd say that in most cases, this does not matter for the main function, but declaring other functions as for example int foo() with empty parenthesis instead of int foo(void) could cause problems, because they mean different things. From the C standard:
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
Here is a question related to that: What are the semantics of function pointers with empty parentheses in each C standard?
One could also argue about a few other things, but some people would disagree about these.
Why declare i outside the for loop? Declaring it inside have been legal since C99, which is 20 years old.
Why end the function with return 0? Omitting this is also ok since C99. You only need to have a return in main if you want to return something else than 0. Personally, in general I find "it's good practice" as a complete nonsense statement unless there are some good arguments to why it should be good practice.
These are good to remember if your goal is to maintain very old C code in environments where you don't have compilers that supports C99. But how common is that?
So if I got to rewrite the example at tutorialspoint, i'd write it like this:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(void){
srand(time(NULL));
for (int i = 0; i < 5; i++) {
printf("%d\n", rand() % 50);
}
}
Another horrible example can be found here: https://www.tutorialspoint.com/c_standard_library/c_function_gets.htm
The function gets is removed from standard C, because it's very dangerous. Yet, the site does not even mention that.
Also, they teach you to cast the result of malloc https://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm which is completely unnecessary. Read why here: Do I cast the result of malloc?
And although they mention that malloc returns NULL on failure, they don't show in the examples how to properly error check it. Same goes for functions like scanf.
I have a function which returns an integer value. Now I want to write a macro which call this function, gets the return value and prepends a string to it and return the resultant string.
I have tried this:
#define TEST(x) is_enabled(x)
I call this macro in the main function as:
int ret = 0;
ret = TEST(2);
printf("PORT-%d\n", ret);
This works perfectly. However I want the macro to return the string PORT-x, where, x is the return value of the called function. How can I do this?
EDIT :
I also tried writing it into multiple lines as:
#define TEST(x)\
{\
is_enabled(x);\
}
And called it in the main function as:
printf("PORT-%d\n", TEST(2));
But this gives a compile time error:
error: expected expression before â{â token
Use a function, not a macro. There is no good reason to use a macro here.
You can solve it by using sprintf(3), in conjonction with malloc or a buffer. See Creating C formatted strings (not printing them) or man pages for details.
About your edit: You don't need to use braces {} in a macro, and they are causing your error as preprocessing would translate it to something like
printf("format%d", {
is_enabled(x);
});
To better understand macros, run gcc or clang with -E flag, or try to read this article: http://en.wikipedia.org/wiki/C_preprocessor
That's a bit of a pain since you need to ensure there's storage for the string. In all honesty, macros nowadays could be reserved for conditional compilation only.
Constants are better done with enumerated types, and macro functions are generally better as inline functions (with the knowledge that inline is a suggestion to the compiler, not a demand).
If you insist on using a macro, the storage could be done with static storage though that has problems with threads if you're using them, and delayed/multiple use of the returned string.
You could also dynamically allocate the string but then you have to free it when done, and handle out-of-memory conditions.
Perhaps the easiest way is to demand the macro user provide their own storage, along the lines of:
#include <stdio.h>
#define TEST2_STR(b,p) (sprintf(b,"PORT-%d",p),b)
int main (void) {
char buff[20];
puts (TEST2_STR(buff, 42));
return 0;
}
which outputs:
PORT-42
In case the macro seems a little confusing, it makes use of the comma operator, in which the expression (a, b) evaluates both a and b, and has a result of b.
In this case, it evaluates the sprintf (which populates the buffer) then "returns" the buffer. And, even if you think you've never seen that before, you're probably wrong:
for (i = 0, j = 9; i < 10; i++, j--)
xyzzy[i] = plugh[j];
Despite most people thinking that's a feature of for, it's very much a different construct that can be used in many different places:
int i, j, k;
i = 7, j = 4, k = 42;
while (puts("Hello, world"),sleep(1),1);
(and so on).
Can if defined (XX) be placed inside a struct/union in a header file?
struct
{
int i;
#if defined(xx)
int j;
#endif
}t;
I am dealing with a large file base of .c and .h files and I need to know the possible cons of this type of usage.
While completely valid, a definite con to using this is any time you need to use t.j you would also have to surround it with your #if defined(xx) otherwise you will invoke compiler errors
Sure you can. The preprocessor can be used for anything, no need to feed it C. The cons of this useage are, that you have a struct which changes size depending on wether xx is defined or not. This is asking for trouble, because a library built with this define and somebody using this library without the define are having different structs....
Preprocessor directives such as #if can be placed anywhere in your program. They have no actual relationship to the C code (or anything else) that is present in the text (except comments), since they are processed before the compilation phase. You can do stupid things like the code below, although it is generally a bad idea.
int foo(int x)
{
#if defined MONKEY
return 0;
}
int bar(int x)
{
#endif
return x;
}
I'm working through K & R to learn programming. Going well so far, but I'm unclear about the role of a line of code from section 1.8 (functions).
In section 1.8, the authors show you how to create a function to raise one integer to the power of another integer.
I've pasted the code below, as it was written in the book. Everything outputs fine. But I don't know why they've included this line at the top:
int power(int m, int n);
The book doesn't mention it, apart from saying that the program will raise integer m to the power n. If I remove the line from the code, the program still outputs as it should.
If I understand this correctly, the line
int power(int base, int n)
creates the function, and the braces underneath define the function. Then the braces under main call the function to output the chart.
So all that seems to make sense. But I don't see what the very top line does.
It could be extraneous, but it seems far more likely that I'm missing something. Can anyone enlighten me as to why that line is there?
#include <stdio.h>
int power(int m, int n);
/* test power function */
main()
{
int i;
for (i = 0; i < 10; ++i)
printf("%d %d %d\n", i, power(2,i), power(-3, i));
return 0;
}
/* power: raise base to n-th power; n >= 0 */
int power(int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
The first line is the declaration of the function. The block of code at the bottom is the definition of the function.
Starting with the 1999 version of the ISO C standard, it's illegal (a constraint violation) to call a function without a visible declaration; the declaration must precede the call.
For a simple program like this one, you could just write the full definition of power() before the definition of main() (since a definition also provides a declaration), but for more complex cases (such as recursive calls) you often need to provide a separate declaration.
For larger programs, it's common to collect all the function declarations in a header file (foo.h, for example), and the corresponding definitions in a source file (foo.c, for example). A #include "foo.h" directive is used to make the declarations visible in other files. You'll see that kind of thing later in the book.
(In the 1990 and earlier versions of C, which is what K&R2 covers, there are cases where you can call a function without a visible declaration -- but it's still a very good idea to provide explicit declarations anyway.)
Incidentally, the declaration of the main program should really be int main(void) rather than just main().
Terminology: a "prototype" is a function declaration that specifies the types of the parameters.
int power(int base, int n); /* a declaration that's also a prototype */
int power(int, int); /* likewise */
int power(); /* a declaration but not a prototype */
(Parameter names are required in a definition, but optional in a standalone declaration.)
As a special case, a prototype for a function with no parameters uses (void), since empty parentheses already mean a non-prototype declaration. So int main(void) is a prototype, but int main() isn't.
Non-prototype declarations are "obsolescent", meaning that they could in theory be removed from a future language standard. But they've been obsolescent since 1989, and even in the new 2011 ISO C standard the committee hasn't seen fit to remove them.
int power(int m, int n);
is a declaration of the power function in its prototype form. A function declaration informs the compiler of the number of parameters the function has, the type of the function parameters and the type of the function return value.
In C you cannot use a function identifier before it has been declared.
It's a forward declaration which makes the function interface public as the function is used before it is actually implemented below main().
Header files, which you #include provide a similar functionality of making the callable API public---but the code is then commonly supplied in a library rather than via the same compilation unit as it is here in this single-file example of the K&R Intro chapter.
If you don't include that line at the top, when the program reaches power(2,i) in main power has not been declared yet. Programs are read from top to bottom, and by putting the declaration at the top, the compiler knows that "a definition is coming".
That line is just the function prototype. It's a forward declaration that allows code to be able to use some function with that signature that will exist when everything is linked together. Without it, the main() function will attempt to use the power() function but the compiler is not aware of it yet since it isn't actually defined later in the source file.
That line at the top that you are referring to is a function prototype. The ONLY thing it is there for is so that the compiler can check your work, that is, to make sure you are using the function correctly by passing the right types and number of arguments. That's all it is for. That is why you can remove it and the code still compiles - all you are doing by removing it is removing the compiler's reference so it can't check your work. And if you do remove it, then there is the possibility that you could pass the wrong type of argument(s) and cause a hard to find run time error or program crash. But leaving it in allows the compiler to flag such an error at compile time saving you some grief. And saving someone some grief is a good thing.
Later, with the C99 standard, they decided to make it mandatory to provide a function prototype (or else define the function first) in order for the code to compile, thus forcing you to let the compiler check your work.
Following is the C Code :
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int a,b,d;
void Values1()
{
a=a*2;
b=b-5;
}
void Values2(register int c)
{
d+=b-c;
a=a+10;
b*=3;
}
int a,b;
int main()
{
int i=7;
Values2(i);
Values1();
printf("a=%d, b=%d, d=%d\n",a,b,d);
system("pause");
}
It Gives a Compilation Error related to redefinition of 'a' and 'b' in MS Visual C++ 2010.
Please help me in figuring out why this error has occured.
You define a and b in the global scope here:
int a,b,d;
and here
int a,b;
You can not define variables twice.
Your compiler is badly configured. Your program is legal C.
The re-declarations of a and b fall into the category of "tentative definition". A properly configured C compiler, cannot stop compilation because of that.
Why do you have these two lines?
int a,b,d;
int a,b;
You only need to define the variables once. I'd suggest getting rid of the second line.
Some other things you may want to consider in the interests of furthering your skills.
Global variables are usually consider a bad thing. There are better ways to do it which encapsulate information much better, and will reduce the likelihood of problems down the track.
Use meaningful variable names. They only slow down the compiler the tiniest bit and will not affect your running speed, but they make your code so much easier to maintain.
I like to space out expressions to make them more readable as well, like d += b - c; instead of d+=b-c;.
Don't bother with the register keyword, it's a suggestion to the compiler and most modern compilers are far better than developers at figuring out how best to optimise code.
There are two canonical prototypes for main and int main() isn't one of them - use int main (void) if you don't care about program arguments.
On pre-C99 compilers, you should return 0 from main (C99 will return 0 for you if you reach the closing brace of main).
Right after the definition of Values2(), there is the line int a,b; which will conflict with int a,b,d; before Values1(), so you can safely remove the line int a,b;.
Besides, to get good results, you may want to set tha values of a, b and c in the start of the main function to get consistent results.