What's meaning of this code in C? - c

In some Bison code, what does the following line mean?
#define YY_DECL extern "C" int yylex();
I know #define command but I don't understand the whole command.

It means that YY_DECL will be expanded to
extern "C" int yylex();
This is actually C++, not C; when you compile this file with a C++ compiler, it declares that the function yylex must be compiled with "C linkage", so that C functions can call it without trouble.
If you don't program in C++, this is largely irrelevant to you, but you may encounter similar declarations in C header files for libraries that try to be compatible with C++. C and C++ can be mixed in a single program, but it requires such declarations for function to nicely work together.
There's probably an #ifdef __cplusplus around this #define; that's a special macro used to indicate compilation by a C++ compiler.

#define YY_DECL extern "C" int yylex();
Define a macro YY_DECL standing for the declaration of a function yylex that has 'C' linkage inside a C++ program, taking no arguments and returning an int.

#define - a preprocessor directive declaring a new variable for the preprocessor. But you know that.
YY_DECL - the name of the variable.
extern "C" - tells the compiler that the following code is pure C. There are a lot of differences between C and C++ and one cannot generally mix C and C++ code. If you include this into declaration, it allows you to use C in C++. EDIT: The code actually not need to be pure C, but it will be linked as such. But the most common usage pattern is to make a C code compatible with C++. Thanks #larsmans for the correction.
int yylex() - a declaration of a function named yylex with undefined number of parameters and return type int
So the whole command assigns a C function declaration to a preprocessor variable.

Related

Correct use of extern when using global variables imported from standard library?

I am trying to learn the use of the extern keyword. As an example I am using the getopt C library function. From my understanding of the extern keyword, it used to indicate to the compiler that a certain variable that has been defined in another file is going to be used. So whenever I am going to be using the getopt variables like opterr, optind, etc, should I(would it be wrong of me to) do this:
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
extern int optopt;
extern int opterr;
extern int optind;
extern char *optarg;
int main(int argc, char **argv) {
/* code using getopt */
}
When I looked at the manpage for getopt(3), I saw these declarations already mentioned under #include <unistd.h>. So I thought that these were declared in that header file but when I looked into the header file itself, there was no such declaration.
So my question is: is there anything wrong with using these statements at the beginning even if for the sake of improving readability for someone who doesn't how getopt works. Also, at the end of the day if the linker is going to resolve references, anyways, is there any reason to use extern at all?
Also, at the end of the day if the linker is going to resolve references, anyways, is there any reason to use extern at all?
The extern keyword can tell the compiler that an unknown symbol is going to be provided by another file.
Consider the situation where we have file1.c with:
int myvariable;
And file2.c with:
#include <stdio.h>
int main() {
myvariable = 10;
printf("myvariable is %d\n", myvariable);
return 0;
}
Attempting to compile this will fail with:
file2.c: In function ‘main’:
file2.c:4:5: error: ‘myvariable’ undeclared (first use in this function)
4 | myvariable=10;
Adding the appropriate extern declaration to file2.c allows us to compile it without errors:
#include <stdio.h>
extern int myvariable;
int main() {
myvariable = 10;
printf("myvariable is %d\n", myvariable);
return 0;
}
Header files can be nested.
unitstd.h includes many other files, the specific declarations you are looking for are in getopt.h,
These statements do not improve readability, they decrease it by adding duplicate garbage code.
A programmer familiar with C but not with getopt function would think these are your custom variables, not part of the standard library, because nothing in the standard library should be redeclared.
The linker is the last step in building the executable.
The external keyword is for the compiler to know the names and types, so it can build code with references for the linker to resolve later.
While it's OK to have more than one declaration for a function or object, as a rule it's best not to redeclare anything declared in a standard library header. It might cause issues if what you declared doesn't exactly match what's in the headers.
Also, just because the man pages say to include unistd.h doesn't necessarily mean the declaration is in that specific file. The declaration in question could be in a file that unistd.h includes. All it means is that including unistd.h will give you the required declaration.

C function prototype in Bash source code with two names? [duplicate]

The usual form of function pointer definitions is:
int function(int, int);
int (*ptr)(int, int);
but I saw a form today which I didn't understand. Can anyone explain this please?
int (*close) __P((struct __db *));
The __P() macro is usually used to support C implementations from the days of K&R C, when there were no prototypes (which were introduced to C with C89). Basically the logic is
#if SOME_LOGIC_TO_TEST_WHETHER_IMPLEMENTATION_SUPPORTS_PROTOTYPES
# define __P(argument_list) argument_list
#else
# define __P(argument_list) ()
#endif
Can you see how this works when applied to your example? Note that for this to work and not cause a syntax error, the argument list must include the parentheses of the function call, not just the parentheses of the function-like macro. Hence the double parentheses when the macro is used. That's probably the reason why it looks unusual.
__P() is just a macro. On my system it is defined as follows (in sys/cdefs.h):
#if defined(__STDC__) || defined(__cplusplus)
#define __P(protos) protos /* full-blown ANSI C */
#else /* !(__STDC__ || __cplusplus) */
#define __P(protos) () /* traditional C preprocessor */
#endif /* !__GNUC__ */
From this, it seems to be used to maintain compatibility with (very) old compilers.
The usual form of function pointer definitions is .... but I saw a
form today which I didn't understand.
There is nothing special here, no magic syntax. This is not a different form of function pointer declaration.
This is just the standard form of function pointer declaration, and __P() is a macro defined by one of the header files that you are using. So, find that macro definition to learn what its purpose is.

Function Pointer Declaration - what does __P do?

The usual form of function pointer definitions is:
int function(int, int);
int (*ptr)(int, int);
but I saw a form today which I didn't understand. Can anyone explain this please?
int (*close) __P((struct __db *));
The __P() macro is usually used to support C implementations from the days of K&R C, when there were no prototypes (which were introduced to C with C89). Basically the logic is
#if SOME_LOGIC_TO_TEST_WHETHER_IMPLEMENTATION_SUPPORTS_PROTOTYPES
# define __P(argument_list) argument_list
#else
# define __P(argument_list) ()
#endif
Can you see how this works when applied to your example? Note that for this to work and not cause a syntax error, the argument list must include the parentheses of the function call, not just the parentheses of the function-like macro. Hence the double parentheses when the macro is used. That's probably the reason why it looks unusual.
__P() is just a macro. On my system it is defined as follows (in sys/cdefs.h):
#if defined(__STDC__) || defined(__cplusplus)
#define __P(protos) protos /* full-blown ANSI C */
#else /* !(__STDC__ || __cplusplus) */
#define __P(protos) () /* traditional C preprocessor */
#endif /* !__GNUC__ */
From this, it seems to be used to maintain compatibility with (very) old compilers.
The usual form of function pointer definitions is .... but I saw a
form today which I didn't understand.
There is nothing special here, no magic syntax. This is not a different form of function pointer declaration.
This is just the standard form of function pointer declaration, and __P() is a macro defined by one of the header files that you are using. So, find that macro definition to learn what its purpose is.

Error: "expected '(' before string constant"

Working on computing the geometric mean of values in an array
The function should compute the geo mean correctly, but i'm getting a weird error message
#include <stdio.h>
#include <stdint.h>
#include <math.h>
extern "C"
double geomean(double myarray[], int count) ////error here, expected '(' before string constant
{
double geomean = 1;
double root = (1/(double)count);
int i;
for(i = 0; i < count; i++)
{
geomean = geomean * myarray[i];
}
geomean = pow(geomean, root);
return geomean;
}
extern "C" is not valid C (it's only valid in C++). Just remove it if you're working in pure C.
I am answering this question in an attempt to cover that could have been covered in more detailed answer to aid the questioner or other persons visiting this page.
Error: “expected '(' before string constant”
As mentioned in some other answer of your question, extern "C" is not valid C (it's only valid in C++). You can remove it if you're using only pure C.
However, if you (or someone else) have a mix of C and C++ source files, then you can make use of macro __cplusplus. __cplusplus macro will be defined for any compilation unit that is being run through the C++ compiler. Generally, that means .cpp files and any files being included by that .cpp file.
Thus, the same .h (or .hh or .hpp or what-have-you) could be interpreted as C or C++ at different times, if different compilation units include them. If you want the prototypes in the .h file to refer to C symbol names, then they must have extern "C" when being interpreted as C++, and they should not have extern "C" when being interpreted as C (as in your case you were getting an error!).
#ifdef __cplusplus
extern "C" {
#endif
// Your prototype or Definition
#ifdef __cplusplus
}
#endif
Note: All extern "C" does is affect linkage. C++ functions, when compiled, have their names mangled. This is what makes overloading possible. The function name gets modified based on the types and number of parameters, so that two functions with the same name will have different symbol names.
If you are including a header for code that has C linkage (such as code that was compiled by a C compiler), then you must extern "C" the header -- that way you will be able to link with the library. (Otherwise, your linker would be looking for functions with names like _Z1hic when you were looking for void h(int, char)).
the first line should be: extern C;
The other option would be declaring c outside the main function without the extern keyword...

Can I substitute __func__ into an identifier name in a C macro?

I'd like to write a C macro which takes this:
int foo() {
MY_MACRO
}
and expands it to this:
int foo() {
_macro_var_foo++;
}
I've found that I can't use __func__, because that doesn't actually get expanded in the macro; it's treated by the preprocessor like a variable.
Is there some way to get this to work?
The preprocessor doesn't know about functions, just source files and line numbers. At that stage it's not performing syntactical analysis, just textual analysis and substitutions. That's why __func__ is a magical variable instead of a magical macro like __FILE__ and __LINE__.
In the C99 standard, __func__ is given a special new category of 'predefined identifier' (in section 6.4.2.2 Predefined Identifiers):
The identifier __func__ shall be implicitly declared by the translator as if,
immediately following the opening brace of each function definition, the declaration
static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing function
This means that it is out of the scope of the C preprocessor, which is not aware of function boundaries or function names. Further, it would expand to a string, which makes it inappropriate for embedding into a variable name.
The GCC (4.4.1) manual says in section 5.43 (Function Names as Strings):
These identifiers [meaning __func__, __FUNCTION__ and __PRETTY_FUNCTION__] are not preprocessor macros. In GCC 3.3 and earlier, in C only, __FUNCTION__ and __PRETTY_FUNCTION__ were treated as string literals; they could be used
to initialize char arrays, and they could be concatenated with other string literals. GCC
3.4 and later treat them as variables, like __func__. In C++, __FUNCTION__ and __PRETTY_FUNCTION__ have always been variables.
If there was a way to get the function name into a preprocessor cleanly, then it is probable that the documentation here would have cross-referenced it, if it did not define it.
Technically, the answer to your question is "yes", there is "some way". But I think you already knew that, and it's true that you cannot deal with this at the macro preprocessor level.
Sure, there is always a way, you just might need a really long tape on that Turing Machine.
I think you already know this, but for the record you can get the overall result you want with:
#define MY_MACRO f_dictionary(__func__, ADDONE);
So now, you just need to implement f_dictionary and an ADDONE op for it.
You can do this using token concatenation.
#define MY_MACRO(baz) _macro_var_##baz++;
#define FUNC_WRAPPER(bar)\
int bar()\
{\
MY_MACRO(bar)\
}
FUNC_WRAPPER(foo)
The output from gcc -E:
int foo(){ _macro_var_foo++;}
Version dealing with argument lists using variadic macros and x macros:
#define MY_MACRO(baz) _macro_var_##baz++;
#define FUNC_DEF(ret_type,bar,...)\
ret_type bar(__VA_ARGS__)\
{\
MY_MACRO(bar)\
FUNC_CONTENTS\
}
#define FUNC_CONTENTS\
printf("Do some stuff\n", s1, s2);
FUNC_DEF(int, foo, char *s1, char *s2)
#undef FUNC_CONTENT

Resources