Meaning of declaration of function - c

I've been reading the stdio.h file and I'm confused.
For example, there is this line:
_CRTIMP FILE* __cdecl __MINGW_NOTHROW fopen (const char*, const char*);
I know FILE* means returning type and I found that _CRTIMP is constant, defined as
# ifndef _CRTIMP
# define _CRTIMP __declspec(dllimport)
# endif
I don't understand it, what is it there for? And what are rest of strings (__cdecl, __MINGW_NOTHROW) ?

__declspec(dllimport) specifies that the function is to be imported from a separate dll; I suppose that, depending on the CRT static/dynamic linking settings, it's defined in different ways.
__cdecl is the calling convention used for the function; the calling convention tells to the compiler how the function expects to be called (in which order parameters are pushed on the stack, if any register is used for parameters, where the return value is stored, who is responsible for stack cleanup, ...); in general you shouldn't worry about it as long as you're not writing libraries.
__MINGW_NOTHROW is #defined to expand to __attribute__ ((__nothrow__)), which is a MinGW-specific extension that tells to the compiler that the function will not throw exceptions; this lets the compiler perform some optimizations.
Note that all these are not standard C attributes, but compiler/platform specific stuff. Again, in general you shouldn't worry about them, they are required to make the CRT work fine, but as long as you're not building libraries you can get away without knowing anything about them. :)

You should take a look at _mingw.h and the gcc manual: In case of gcc - or any other compiler supporting __GNUC__ - the following definitions apply:
#define __cdecl __attribute__ ((__cdecl__))
#define __MINGW_NOTHROW __attribute__ ((__nothrow__))
The former tells the compiler to use the cdecl x86 calling convention (see gcc manual), the latter that the function is guaranteed not to throw C++ exceptions (see gcc manual).
__declspec(dllimport) is necessary to make dynamic linking work (see gcc manual).

__declspec(dllimport) tells the compiler that this function needs to be imported from a DLL, it's a Windows-specific extension. See this page for details.
Likewise, __cdecl is an attribute that specifies that the function uses a particular calling convention (namely, the one used by C). See this page.
I would guess that the __MINGW_NOTHROW macro is a synonym for the GCC nothrow attribute, which informs the compiler that the function in question cannot throw exceptions. See the documentation for details.

Theses are declarations specific to the environment or the compiler you're using.
The __declspec(dllimport) indicates, on windows, that this function is in a dll and should be placed in the import table of the executable PE file generated.
The __cdecl indicate a standard C calling convention and will modify the way the compiler transform the function to conform to this calling convention.
__MINGW_NOTHROW is specific to your compiler and might de-activate support for exception.
In all case, there must be an explanation in the documentation of your compiler.

Related

What are these function and parameter annotations?

The source code for busybox's syslogd implementation contains some annotations I'm unfamiliar with. The language is C, not C++.
int syslogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int syslogd_main(int argc UNUSED_PARAM, char **argv)
Specifically, MAIN_EXTERNALLY_VISIBLE and UNUSED_PARAM.
What exactly are these annotations doing? Where can I read more about them and other annotations?
Are these part of the C standard, or are they compiler extensions? If they are compiler extensions, how widely supported are they?
I assume the first one is why this file doesn't have a main() function. If these are compiler extensions rather than part of the standard, does this mean this file can't be meaningfully compiled as-is by a compiler that adheres only to the C standard?
Why did they declare a prototype of the syslogd_main function immediately before the full definition? Can the MAIN_EXTERNALLY_VISIBLE annotation only be applied to function prototypes?
1. What exactly are these annotations doing?
See include/platform.h and include/libbb.h
UNUSED_PARAM expands to __attribute__ ((__unused__)). It specifies the variable (argc in your example) as "possibly unused" and disables the "unused variable" warning.
From the GCC manual [Specifying Attributes of Variables]:
unused
This attribute, attached to a variable, means that the variable is meant to be possibly unused. GCC will not produce a warning for this variable.
MAIN_EXTERNALLY_VISIBLE expands to EXTERNALLY_VISIBLE and then to __attribute__(( visibility("default") )). It controls the visibility of the function.
From the GCC manual [Declaring Attributes of Functions]:
... On ELF, default visibility means that the declaration is visible to other modules and, in shared libraries, means that the declared entity may be overridden.
From include/libbb.h:
/* We need to export XXX_main from libbusybox
* only if we build "individual" binaries
*/
#if ENABLE_FEATURE_INDIVIDUAL
#define MAIN_EXTERNALLY_VISIBLE EXTERNALLY_VISIBLE
#else
#define MAIN_EXTERNALLY_VISIBLE
#endif
2. Are these part of the C standard, or ...?
No, those are macros defined in the BusyBox project.
3. I assume the first one is why this file doesn't have a main() function. ...
No. BusyBox combines many utilities into a single executable. That explains the "lack of a main() function" in syslogd.c.
4. Why did they declare a prototype of the syslogd_main function immediately before the full definition? ...
From the GCC manual [Declaring Attributes of Functions]:
The keyword __attribute__ allows you to specify special attributes when making a declaration.

What is the __builtin_expect() prototype?

To get rid of a static code analysis warning (QA-C), I need to provide a function prototype for __builtin_expect().
I am using the WindRiver Diab compiler for PowerPC.
In the compiler manual I have found the following information:
__builtin_expect(long exp, long c): ... exp is also the return value.
So, my prototype is as follows:
long __builtin_expect(long exp, long c);
However, it does not compile, I am getting the following error:
error (dcc:1701): invalid types on prototype to intrinsic __builtin_expect - when the intrinsic is enabled, optional user prototype must match
It seems like my prototype is not correct. What is the correct prototype for __builtin_expect?
The error message states that the user prototype is optional. So it should be possible to define it, right?
You need to somehow define __builtin_expect to make your static analyzer happy, because it doesn't know what that function is. But you need to use #ifdef to disable that definition when you are compiling your program normally, because your compiler will not like it if you try to define compiler builtins yourself. The builtins come with the compiler so they are not supposed to be defined in your program.
Something like this would work:
#ifdef _HEY_I_AM_RUNNING_STATIC_ANALYZER
#define __builtin_expect(e,c) (e)
#endif
I don't know the details of how your static analyzer works, so I don't know what the right macro is to test in the #ifdef. You can read the documentation of your static analyzer to find out if it defines any preprocessor symbols by default, or if you can tell it what preprocessor symbols to define when you run it.
You should carefully read the documentation of Other Builtins in GCC.
As a first approximation, you might replace __builtin_expect by (invocation _builtin_expect_replacement of) the macro below:
#define _builtin_expect_replacement(Exp,C) (Exp)
For most static analyzers that should be enough
Don't expect most GCC builtins to be definable as functions.

What do DECLSPEC and SDLCALL mean in a function definition in a header file on Linux mean?

I was poking around the SDL 2 header files, and found that the majority of functions that I encountered had this form:
extern DECLSPEC int SDLCALL SDL_FunctionName();
I understand what extern, int, and SDL_FunctionName all mean (the storage class specifier, return value, and function name, respectively). However, I must admit that I have not seen the likes of DECLSPEC and SDLCALL before. Searches for the former merely yield a Win32/64 API thing, and nothing good comes up for the latter.
What do these two things mean, and what do they do?
These are constants defined to change the export behavior of a symbol (the function) by the C/C++ compiler.
DECLSPEC is a macro used in C/C++ header files. It stands for either __declspec(dllexport) or __declspec(dllimport) depending on whether you are the project library or the consumer. See here for more details.
In the declaring/owning project of the class, DECLSPEC resolves to __declspec(dllexport). This tells the compiler to allow access to these functions from outside the DLL. It also changes the default naming behavior of the compiler (called name decoration or name mangling) to allow easier access to these symbols from outside the DLL. See here.
In the consuming project, DECLSPEC resolves to __declspec(dllimport). This is not strictly necessary, but its use allows the compiler to generate more efficient code for the consumed symbols, such as in generation of thunks. See here.
SDLCALL would be a constant which declares the calling convention of the function. You can read more about calling conventions such as __stdcall, __cdecl, etc. here.
These macros are used to make the program portable across many different architectures and platforms, just by redefining the constants. Usually, the compiler or SDK used on the platform has these macros globally defined.
SDLCALL
SDLCALL would be calling convention that this function should be implemented. This tells who pushes arguments to the function (caller or callee) and who clears the stack when function returns.
MSDN has some detail info here about different calling conventions.
DECLSPEC
Signifies that this function can be candidate for exported function. Its mainly used in Windows to export a function from DLL.
If you look in SDL's headers you'll find begin_code.h which has the following snippet to define DECLSPEC:
/* Some compilers use a special export keyword */
#ifndef DECLSPEC
# if defined(__WIN32__) || defined(__WINRT__)
# ifdef __BORLANDC__
# ifdef BUILD_SDL
# define DECLSPEC
# else
# define DECLSPEC __declspec(dllimport)
# endif
# else
# define DECLSPEC __declspec(dllexport)
# endif
# else
# if defined(__GNUC__) && __GNUC__ >= 4
# define DECLSPEC __attribute__ ((visibility("default")))
# elif defined(__GNUC__) && __GNUC__ >= 2
# define DECLSPEC __declspec(dllexport)
# else
# define DECLSPEC
# endif
# endif
#endif
and SDLCALL:
/* By default SDL uses the C calling convention */
#ifndef SDLCALL
#if (defined(__WIN32__) || defined(__WINRT__)) && !defined(__GNUC__)
#define SDLCALL __cdecl
#else
#define SDLCALL
#endif
#endif /* SDLCALL */
So it looks like for Linux, DECLSPEC will be defined to:
__attribute__ ((visibility("default")))
or
__declspec(dllexport)
depending on the version of GCC being used and SDLCALL will be defined to nothing.
on other platforms, those macros may have different definitions depending on the needs of the particular platform and compiler being used.
They are preprocessor definitions. They are used to make the code cross platform, as DLL modifiers are required on Windows. When the library is being built as a DLL on Windows, it is defined as __declspec(dllexport) so the function is externally visible. When the headers are being used by an application linked to the DLL on Windows, it is defined as __declspec(dllimport) so the compiler knows to look for it in an external DLL. See the source code here to see exactly how they are defined.
Here's the GCC wiki page on visibility. http://gcc.gnu.org/wiki/Visibility
Shared libraries contain a list of all the symbols (names of functions and variables) that can be accessed from linking applications. On Linux the default behavior has long been to expose (store in a list in the shared library) all defined symbols, whether they are needed or not. With the new visibility feature and an extra compiler flag only the needed symbols are in this list, making a smaller, faster-to-link shared library.
The GCC wiki page focuses on C++ where the gains are most dramatic but the feature works for C too.
That's for DECLSPEC. On Linux SDLCALL does nothing but when it is defined it is used to say the functions should use the C calling convention.

How to declare an inline function in C99 multi-file project?

I want to define an inline function in a project, compiled with c99. How can I do it?
When I declare the function in a header file and give the detail in a .c file, the definition isn't recognized by other files. When I put the explicit function in a header file, I have a problem because all .o files who use it have a copy of the definition, so the linker gives me a "multiple definition" error.
What I am trying to do is something like:
header.h
inline void func()
{
do things...
}
lib1.c
#include "header.h"
...
lib2.c
#include "header.h"
with a utility which uses both lib1.o and lib2.o
Unfortunately not all compilers are completely complying to C99 in that point even if they claim that they'd be.
An conforming way to do this is
// header file. an inline definition alone is
// not supposed to generate an external symbol
inline void toto(void) {
// do something
}
// in one .c file, force the creation of an
// external symbol
extern inline void toto(void);
Newer versions of gcc, e.g, will work fine with that.
You may get away with it for other compilers (pretenders) by defining something like
#ifdef PRETENDER
# define inlDec static
# define inlIns static
#else
# define inlDec
# define inlIns extern
#endif
// header file. an inline declaration alone is
// not supposed to generate an external symbol
inlDec inline void toto(void) {
// do something
}
// in one .c file, force the creation of an
// external symbol
inlIns inline void toto(void);
Edit:
compilers with C99 support (usually option -std=c99) that I know of
gcc (versions >= 4.3 IIRC) implements
the correct inline model
pcc is also correct
ggc < 4.3 needs a special option to
implement the correct model,
otherwise they use their own model
that results in multiple defined
symbols if you are not careful
icc just emits symbols in every unit
if you don't take special care. But
these symbols are "weak" symbols, so
they don't generate a conflict. They
just blow up your code.
opencc, AFAIR, follows the old gcc specific model
clang doesn't emit symbols for inline functions at all, unless you have an extern declaration and you use the function pointer in one compilation unit.
tcc just ignores the inline keyword
If used by itself, in C99 inline requires that the function be defined in the same translation unit as it's being used (so, if you use it in lib1.c, it must be defined in lib1.c).
You can also declare a method as static inline (and put the definition in a header file shared between two source files). This avoids the multiple-definition issue, and lets the compiler inline the file across all the translation units where it's used (which it may or may not be able to do if you just declare the function in one translation unit).
See: http://www.greenend.org.uk/rjk/2003/03/inline.html
I think you don't need to use the inline word when you are defining and declaring the function inside the Header file, the compiler usually takes it as inline by default unless it's too long, in which case it will be smart enough to treat it as a normal function.
I think the multiple definition may be caused by the lack of a Include Guard in the Header file.
You should use something like this in the header:
#ifndef HEADERNAME_H
#define HEADERNAME_H
void func()
{
// do things...
}
#endif

multiple definition of inline function

I have gone through some posts related to this topic but was not able to sort out my doubt completely. This might be a very naive question.
I have a header file inline.h and two translation units main.cpp and tran.cpp.
Details of code are as below
inline.h
#ifndef __HEADER__
#include <stdio.h>
extern inline int func1(void)
{ return 5; }
static inline int func2(void)
{ return 6; }
inline int func3(void)
{ return 7; }
#endif
main.c
#define <stdio.h>
#include <inline.h>
int main(int argc, char *argv[])
{
printf("%d\n",func1());
printf("%d\n",func2());
printf("%d\n",func3());
return 0;
}
tran.cpp
//(note that the functions are not inline here)
#include <stdio.h>
int func1(void)
{ return 500; }
int func2(void)
{ return 600; }
int func3(void)
{ return 700; }
The above code compiles in g++, but does not compile in gcc (even if you make changes related to gcc like changing the code to .c, not using any C++ header files, etc.). The error displayed is "duplicate definition of inline function - func3".
Can you clarify why this difference is present across compilers?
Also, when you run the program (g++ compiled) by creating two separate compilation units (main.o and tran.o) and create an executable a.out, the output obtained is:
500
6
700
Why does the compiler pick up the definition of the function which is not inline. Actually, since #include is used to "add" the inline definition I had expected 5,6,7 as the output. My understanding was during compilation since the inline definition is found, the function call would be "replaced" by inline function definition.
Can you please tell me in detailed steps the process of compilation and linking which would lead us to 500,6,700 output. I can only understand the output 6.
This answer is divided into the following sections:
How to reproduce the duplicate definition of inline function - func3 problem and why.
Why defintion of func3 is a duplicate instead of func1.
Why it compiles using g++
How to produce the duplicate definition of inline function - func3 problem
The problem can be successfully reproduced by
Rename tran.cpp to tran.c
Compile with gcc -o main main.c tran.c
#K71993 is actually compiling using the old gnu89 inline semantics, which is different from C99. The reason for renaming tran.cpp to tran.c is to tell the gcc driver to treat it as C source instead of C++ source.
Why definition of func3 is a duplicate instead of func1.
GNU 89 inline semantics
The following text is quoted from GCC Document: An Inline Function is As Fast As a Macro explains why func3 is a duplicate definition instead of func1, since func3 (instead of func1) is an externally visible symbol (in GNU89 inline semantics)
When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline function is always compiled on its own in the usual fashion.
If you specify both inline and extern in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not even if you refer to its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it.
C99 inline semantics
If compiled with C99 standard, i.e., gcc -o main main.c tran.c -std=c99, the linker will complain that definition of func1 is a duplicate due to the reason that extern inline in C99 is a external definition as mentioned in other posts and comments.
Please also refer to this execellent answer about semantic differents between GNU89 inline and C99 inline.
Why it compiles using g++.
When compiled with g++, the source program are considered as C++ source. Since func1, func2 and func3 are defined in multiple translation units and their definitions are different, the One Defintion Rule of C++ is violated. Since the compiler is not required to generate dignostic message when definitions spans multiple translation units, the behavior is undefined.
Maybe you should post the actual code. The snippets you show don't compile:
inline.h has extern inline int func1(void) That doesn't make any sense.
main.h has #define <stdio.h> I think you meant include instead.
Once I fixed those and compiled with gcc, it compiled fine and I got the following output
5
6
7
When I compile with g++, I get this output:
5
6
700
That happens because func3() is not static in inline.h
The compiling error is because there is a duplicate definition of func1();
Because func1() is defined using extern inline, it will produce a external definition.
However, there is also an external definition in tran.c, which cause multiple definition error.
However, func2() and func3() do not produce an external definition, hence no redefinition error.
You might want to look at here http://www.greenend.org.uk/rjk/2003/03/inline.html.
Also, take a note that c++ and c treats inline functions differently, and even in c, different standards (c89 vs. c99) treats inline functions differently.
Your code is invalid from the C++ point of view, since it blatantly violates the One Definition Rule. The only reason you managed to compile it by C++ compiler is the loose error checking in your C++ compiler (it happens to be one of those parts of ODR where "no diagnostic is required").
Your code is not valid C, because it provides duplicate external definition of function func1. Note that it is func1, not func3 that is problematic from the C point of view. There's nothing formally wrong with your func3. Your func2 is also OK, as long as the two definitions never "meet" each other in the same translation unit.
One possible reason you might be getting a different diagnostic report from your compiler is that your C compiler might be supporting inline functions in some non-standard compiler-specific way (either a pre-C99 compiler or a modern compiler run in non-standard "legacy" mode).
Frankly, I find it hard to believe you are getting an error report about func3 from any compiler, assuming the code you posted accurately represents what you are trying to compile. Most likely what you posted is not the real code.
The compile error you see is actually a linker error.
gcc and g++ are treating static inline a little differently. inline was first part of C++ and then made into an extension to many C compilers, before being added to standard C. The standard semantics could be different, but it could just be the implementations that are different.
It could also have something to do with some crazy stuff that happens with C++ code that gets rid of duplicate template stuff catching other duplicate stuff as well.
basically Inline is a late entry to GCC ( I mean c compiler).
"[ . . . ] An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition."
— ISO 9899:1999(E), the C99 standard, section 6.7.4

Categories

Resources