int main()
{
static int fun(){}
return 0;
}
** If we define a function into another then why this code is giving following error:**
Error: invalid storage class for function ‘fun’
This is called "nested function". It's not supported in C. Some compilers, such as gcc, offer it as language extension. You do not need the static keyword though.
C does not support nested functions, simple as that.
To answer the question in comment about gcc non-standard nested functions and static keyword: as explained in the gcc manual (link credit to the other answer):
A nested function always has no linkage. Declaring one with extern or static is erroneous.
In other words, static keyword does not work, because it is explicitly documented to be invalid syntax, because it can not mean what people would expect it to mean.
For comparison, standard C++ has the workaround of being able to define class/struct member functions along with the class/struct also inside a function. And C++11 has proper lambda syntax too. But no such things in standard C.
Related
From the C18 standard:
If all of the file scope declarations for a function in a translation
unit include the inline function specifier without extern, then the
definition in that translation unit is an inline definition.
Then we read:
The declaration of an inline function with external linkage can result
in either an external definition, or a definition available for use
only within the translation unit. A file scope declaration with extern
creates an external definition.
I've written a bit of code to check if the function is actually inline or not. I've used this restriction to find out:
An inline definition of a function with external linkage shall not
contain a definition of a modifiable object with static or thread
storage duration, and shall not contain a reference to an identifier
with internal linkage.
This is the code:
static int n = 5;
void inline foo() { n = 66; }
void inline foo(); // remove 'inline' in second version
int main() {
return 0;
}
When compiling this I get a warning saying that the inline function is using a static object, which means that foo() is, effectively, an inline function, and so it provides an inline (not external) definition. However, when I remove the inline specifier from the indicated line, I don't get the warning anymore. According to the standard, it's not an inline definition, so I guess it's providing an external definition.
What the standard is not saying, or at least I cannot see it, is whether an inline function that provides an external definition stops being an inline function, or not. According to my test, it does stop being an inline function.
If I'm right in my conclusions, which I don't know, another question arises: why an extern inline function is a useless thing?
In the question you try things in the compiler to try and deduce the language rules. This is generally a bad idea, because (a) in many situations the effect of breaking the rules is hard to observe, and (b) the compiler might be bugged. Instead, the Standard is an authoritative source for what the language rules are, so the question should be answered by referring to the Standard.
Moving on: your code contains a constraint violation of C11 6.7.4/3, which you quoted in your question. The effect of a constraint violation is that the compiler must issue a diagnostic, which it did.
Then you ask about some modification, I assume you mean the following code:
static int n = 5;
void inline foo() { n = 66; }
void foo();
int main() { return 0; }
As covered by the first sentence you quoted (from 6.7.4/7), the definition of foo() is not an inline definition, because it is not true that all of the file-scope declarations in the TU include the inline specifier without extern. (That sentence is intended to deny the antecedent).
Since it is not an inline definition, there is no problem with n = 66 and the code is correct.
What the standard is not saying, or at least I cannot see it, is whether an inline function that provides an external definition stops being an inline function, or not
An inline function definition is never an external definition. This is clearly stated in 6.7.4/7 "An inline definition does not provide an external definition for the function".
Maybe your confusion arises from conflating the concepts "inline function definition" and "function definition with the inline specifier".
another question arises: why an extern inline function is a useless thing?
If you mean the keywords extern inline that is another topic that was not touched on by this question, see here. Inline functions with external linkage are certainly not useless .
I feel I need to answer myself, as this is even more complex than I expected at the beginning, and new facts have arisen during my research since I wrote the question. This is more like my own conclusions, but I feel I'm in the right path. So I need to share. Feedback and confirmation/rejection will be most appreciated.
In the first place, take a look at this code:
void inline foo() { return; }
int main() {
foo();
return 0;
}
It might seem like a simple code, but the fact is that it doesn't compile. Well, actually, it compiles, but it fails in the linker step. Why? Let's read the full difficult-to-understand paragraph from the standard:
For a function with external linkage, the following restrictions
apply: If a function is declared with an inline function specifier,
then it shall ALSO be defined in the same translation unit. If all of
the file scope declarations for a function in a translation unit
include the inline function specifier without extern, then the
definition in that translation unit is an inline definition. 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.
From "It is unspecified whether a call to the function uses the inline definition or the external definition" we get the answer of why it didn't compile (link) well. My implementation (GCC) chose the external version. And the linker doesn't know about such external function.
The standard says an inline definition "does not forbid an external definition in another translation unit". Actually it doesn't, but it even makes mandatory to define it elsewhere if the function is called from the present translation unit and the implementation chooses to call the external version.
Then, another question arises: if the implementation choses to call the external definition, or the inline definition, why is it necessary to define both? Well I found the answer in GCC documentation: you never know when one will be chosen or the other. For instance, GCC chooses the external version when no optimizer switches are indicated. For many optimized code configurations, inline versions will be chosen.
And regarding the question about why inline extern functions could be useless, actually they are not. External functions can also be inlined. Check this document: https://gcc.gnu.org/onlinedocs/gcc/Inline.html
An external inline function can be used and inlined from other translation units, it just doesn't create an inline definition. Inline definitions are only useful when you want to have alternative versions of a function that are used depending on optimization switches, for instance.
However, I think the standard is not very clear about the inlining of external inline functions. What GCC does, for example is: non-static inline functions are not inline functions, unless they have inline and extern specifiers in the declaration (not in the external definition) of the function.
I read several questions in stackoverflow about inline in C but still am not clear about it.
static inline void f(void) {} has no practical difference with static void f(void) {}.
inline void f(void) {} in C doesn't work as the C++ way. How does it work in C?
What actually does extern inline void f(void); do?
I never really found a use of the inline keyword in my C programs, and when I see this keyword in other people's code, it's almost always static inline, in which I see no difference with just static.
A C code can be optimized in two ways: For Code size and for Execution Time.
inline functions:
gcc.gnu.org says,
By declaring a function inline, you can direct GCC to make calls to that function faster. One way GCC can achieve this is to integrate that function's code into the code for its callers. This makes execution faster by eliminating the function-call overhead; in addition, if any of the actual argument values are constant, their known values may permit simplifications at compile time so that not all of the inline function's code needs to be included. The effect on code size is less predictable; object code may be larger or smaller with function inlining, depending on the particular case.
So, it tells the compiler to build the function into the code where it is used with the intention of improving execution time.
If you declare Small functions like setting/clearing a flag or some bit toggle which are performed repeatedly, inline, it can make a big performance difference with respect to time, but at the cost of code size.
non-static inline and Static inline
Again referring to gcc.gnu.org,
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.
extern inline?
Again, gcc.gnu.org, says it all:
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.
This combination of inline and extern has almost the effect of a macro. The way to use it is to put a function definition in a header file with these keywords, and put another copy of the definition (lacking inline and extern) in a library file. The definition in the header file causes most calls to the function to be inlined. If any uses of the function remain, they refer to the single copy in the library.
To sum it up:
For inline void f(void){},
inline definition is only valid in the current translation unit.
For static inline void f(void) {}
Since the storage class is static, the identifier has internal linkage and the inline definition is invisible in other translation units.
For extern inline void f(void);
Since the storage class is extern, the identifier has external linkage and the inline definition also provides the external definition.
Note: when I talk about .c files and .h files in this answer, I assume you have laid out your code correctly, i.e. .c files only include .h files. The distinction is that a .h file may be included in multiple translation units.
static inline void f(void) {} has no practical difference with static void f(void) {}.
In ISO C, this is correct. They are identical in behaviour (assuming you don't re-declare them differently in the same TU of course!) the only practical effect may be to cause the compiler to optimize differently.
inline void f(void) {} in C doesn't work as the C++ way. How does it work in C? What actually does extern inline void f(void); do?
This is explained by this answer and also this thread.
In ISO C and C++, you can freely use inline void f(void) {} in header files -- although for different reasons!
In ISO C, it does not provide an external definition at all. In ISO C++ it does provide an external definition; however C++ has an additional rule (which C doesn't), that if there are multiple external definitions of an inline function, then the compiler sorts it out and picks one of them.
extern inline void f(void); in a .c file in ISO C is meant to be paired with the use of inline void f(void) {} in header files. It causes the external definition of the function to be emitted in that translation unit. If you don't do this then there is no external definition, and so you may get a link error (it is unspecified whether any particular call of f links to the external definition or not).
In other words, in ISO C you can manually select where the external definition goes; or suppress external definition entirely by using static inline everywhere; but in ISO C++ the compiler chooses if and where an external definition would go.
In GNU C, things are different (more on this below).
To complicate things further, GNU C++ allows you to write static inline an extern inline in C++ code... I wouldn't like to guess on what that does exactly
I never really found a use of the inline keyword in my C programs, and when I see this keyword in other people's code, it's almost always static inline
Many coders don't know what they're doing and just put together something that appears to work. Another factor here is that the code you're looking at might have been written for GNU C, not ISO C.
In GNU C, plain inline behaves differently to ISO C. It actually emits an externally visible definition, so having a .h file with a plain inline function included from two translation units causes undefined behaviour.
So if the coder wants to supply the inline optimization hint in GNU C, then static inline is required. Since static inline works in both ISO C and GNU C, it's natural that people ended up settling for that and seeing that it appeared to work without giving errors.
, in which I see no difference with just static.
The difference is just in the intent to provide a speed-over-size optimization hint to the compiler. With modern compilers this is superfluous.
From 6.7.4 Function specifiers in C11 specs
6 A function declared with an inline function specifier is an inline
function. Making a function an inline function suggests that calls to
the function be as fast as possible.138)The extent to which
such suggestions are effective is
implementation-defined.139)
138) By using, for example, an alternative to the usual function call
mechanism, such as inline substitution. Inline substitution is not
textual substitution, nor does it create a new function. Therefore,
for example, the expansion of a macro used within the body of the
function uses the definition it had at the point the function body
appears, and not where the function is called; and identifiers refer
to the declarations in scope where the body occurs. Likewise, the
function has a single address, regardless of the number of inline
definitions that occur in addition to the external
definition.
139) For example, an implementation might
never perform inline substitution, or might only perform inline
substitutions to calls in the scope of an inline declaration.
It suggests compiler that this function is widely used and requests to prefer speed in invocation of this function. But with modern intelligent compiler this may be more or less irrelevant as compilers can decide whether a function should be inlined and may ignore the inline request from users, because modern compilers can very effectively decide about how to invoke the functions.
static inline void f(void) {} has no practical difference with static
void f(void) {}.
So yes with modern compilers most of the time none. With any compilers there are no practical / observable output differences.
inline void f(void) {} in C doesn't work as the C++ way. How does it
work in C?
A function that is inline anywhere must be inline everywhere in C++ and linker does not complain multiple definition error (definition must be same).
What actually does extern inline void f(void); do?
This will provide external linkage to f. Because the f may be present in other compilation unit, a compiler may choose different call mechanism to speed up the calls or may ignore the inline completely.
A function where all the declarations (including the definition) mention inline and never extern.
There must be a definition in the same translation unit. The standard refers to this as an inline definition.
No stand-alone object code is emitted, so this definition can't be called from another translation unit.
In this example, all the declarations and definitions use inline but not extern:
// a declaration mentioning inline
inline int max(int a, int b);
// a definition mentioning inline
inline int max(int a, int b) {
return a > b ? a : b;
}
Here is a reference which can give you more clarity on the inline functions in C & also on the usage of inline & extern.
If you understand where they come from then you'll understand why they are there.
Both "inline" and "const" are C++ innovations that were eventually retrofit into C. One of the design goals implicit in these innovations, as well as later innovations, like template's and even lambda's, was to carve out the most common use-cases for the pre-processor (particularly, of "#define"), so as to minimize the use of and need for the pre-processor phase.
The occurrence of a pre-processor phase in a language severely limits the ability to provide transparency in the analysis of and translation from a language. This turned what ought to have been easy translation shell scripts into more complicated programs, such as "f2c" (Fortran to C) and the original C++ compiler "cfront" (C++ to C); and to a lesser degree, the "indent" utility. If you've ever had to deal with the translation output of convertors like these (and we have) or with actually making your own translators, then you'll know how much of an issue this is.
The "indent" utility, by the way, balks on the whole issue and just wings it, compromising by just treating macros calls as ordinary variables or function calls, and passing over "#include"'s. The issue will also arise with other tools that may want to do source-to-source conversion/translation, like automated re-engineering, re-coding and re-factoring tools; that is, things that more intelligently automate what you, the programmer, do.
So, the ideal is to reduce dependency on the pre-processor phase to a bare minimum. This is a goal that is good in its own right, independently of how the issue may have been encountered in the past.
Over time, as more and more of the use-cases became known and even standardized in their usage, they were encapsulated formally as language innovations.
One common use-case of "#define" to create manifest constants. To a large extent, this can now be handled be the "const" keyword and (in C++) "constexpr".
Another common use-case of "#define" is to create functions with macros. Much of this is now encapsulated by the "inline" function, and that's what it's meant to replace. The "lambda" construct takes this a step further, in C++.
Both "const" and "inline" were present in C++ from the time of its first external release - release E in February 1985. (We're the ones who transcribed and restored it. Before 2016, it only existed as a badly-clipped printout of several hundred pages.)
Other innovations were added later, like "template" in version 3.0 of cfront (having been accepted in the ANSI X3J16 meeting in 1990) and the lambda construct and "constexpr" much more recently.
As the word "Inline" say "In" "Line", adding this keyword to a function affects the program in runtime, when a program is compiled, the code written inside a function is pasted under the function call, as function calls are more costly than inline code, so this optimizes the code.
So, static inline void f(void) {} and static void f(void) {}, here the inline keyword does make a difference in runtime. But when the function has too many lines of code then it won't affect runtime.
If you add static before a function, the function's lifetime is the lifetime of the whole program. And that function use is restricted to that file only.
To know about extern you can refer to - Effects of the extern keyword on C functions
I am trying to find some official confirmation on a theory with respect to C functions. In a simple project of mine, I have a function which I only want to be visible within the .c file in which it is defined. The function prototype is:
static int sum(int a, int b);
The function definition is:
int sum(int a, int b) {
return (a+b);
}
Upon analysis of the build output, link maps, etc, it seems that the function is indeed static. I'm surprised that I don't get any build warnings or errors either. However, is there anything in terms of documentation (ie: specific line in the GCC manual) that can confirm this behavior, or what is expected?
I have found the equivalent of this question for C++ (Static keyword in function declaration can be missing in function definition?), but I am looking for the answer with respect to pure C.
Thank you.
You can download the full specification from http://www.iso.org/iso/home/store/catalogue_ics/catalogue_detail_ics.htm?csnumber=57853
for 238 Swiss Francs, and I'm sure that will have the answer. Otherwise, the best source I have is from "The C Programming Language" 2nd edition by K&R, section 4.6 on page 83 (emphasis added)
"The external static declaration is most often used for variables, but it can be applied to functions as well. Normally, function names are global, visible to any part of the entire program. If a function is declared static, however, its name is invisible outside of the file in which it is declared."
Note that the quote only refers to the declaration of the function, not its definition, although it's common practice for static functions, that the definition serves as the declaration as well.
The function will be visible only in the .c by default, in order to make it visible to other files you would have to declare its prototype in the header ( .h file ).
Don't think of static here as in Java or other OO languages where only the class can call a static method, it is quite a difference.
The behaviour of static in C is that a function or variable is only known within the scope of the current compile, the data is kept in the executable file generated.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Effects of the `extern` keyword on C functions
Ok, so for a few hours now I've read a lot about what the extern keyword means. And there is one last thing that is bugging me to no end that I cannot find any info about.
As far as I understand the extern keyword basically tells the compiler that the variable or function is only a declaration and that it is defined somewhere, so it doesn't have to worry about that, the linker will handle it.
And the warning generated by the compiler (I'm using gcc 4.2.1) when typing this:
extern int var = 10;
supports this. With extern this should be a declaration only so it is not correct.
However, the thing that is confusing me is the absence of a warning or anything when typing this:
extern int func() {return 5;}
This is a definition, and it should generate the same warning, but it does not. The only explanation to this I was able to find here is that the definition overrides the extern keyword. However, following that logic why does it not override it when it is a variable definition? Or does the keyword have special meaning when used with variables?
I would be most grateful if someone explained this to me. Thank you!
The extern keyword indeed has special meaning only when it is used with variables. Using extern with function prototypes is entirely optional:
extern void foo(int bar);
is equivalent to
void foo(int bar);
When you declaring/defining a function, you have two options:
Provide only a declaration (i.e. a prototype), or
Provide a definition, which also serves as a declaration in the absence of a prototype.
With variables, however, you have three options:
Provide only a declaration,
Provide a definition with the default initializer: int var; without the = 10 part, or
Provide a definition with a specific initializer: int var = 10
Since there are only two options for functions, the compiler can distinguish between then without the use of extern keyword. Any declaration that does not have a static keywords is considered extern by default. Therefore, the extern keyword is ignored with all function declarations or definitions.
With variables, however, the keyword is needed to distinguish between the #1 and the #2. When you use extern, it's #1; when you do not use extern, it's #2. When you try to add extern to #3, it's a warning, because it remains a definition, and the extern is ignored.
All of this is somewhat simplified: you can provide declarations several times in the same compilation unit, and you can provide them at the global scope or at a block scope. For complete details, check section 6.7.9 5 of the C standard.
However, following that logic why does it not override it when it is a variable definition? Or does the keyword have special meaning when used with variables?
The difference between variables and functions is that
void foo();
is a function declaration, but
int i;
is a variable definition.
If you have the variable definition in multiple files, then the compiler will generate the storage for that variable multiple times (and most likely you'll get a linker error). This is not the case for functions.
I implemented a function called abs(). I get this error:
Intrinsic function, cannot be defined
What have I done wrong?
I'm using Visual Studio 2005.
Intrinsic function, cannot be defined
In this case, intrinsic means that the compiler already has an implementation of a function called abs, and which you cannot redefine.
Solution? Change your function's name to something else, snakile_abs for example.
Check the MSDN documentation on the abs function for more information.
The problem is not being in a header or not.
The problem is that intrinsic functions, i.e., functions that the compiler recognizes and implements itself, generally with optimizations that wouldn't be available in C code alone, cannot be defined.
The names of all mathematical functions (see math.h)
The names of all mathematical functions prefixed by 'f' or 'l'.
Are reserved for the implementation.
Defining static int abs(int x) { ... } should be legal, but simply int abs(int x) { ... } has undefined behavior, and thus one reasonable thing a compile could do is issue an error.