I was asked a very interesting question during a C interview: How can you implement a function f() in such a way that it can only be called from a particular g() function. If a function other than g() tries to call f() it would result in a compiler error.
At first, I though this could be done with function pointers and I could get close to blocking the call at runtime. But I was not able to think of a compile time strategy. I don't even know if this is possible using ansi C.
Does anyone have any idea?
Here's one way:
int f_real_name(void)
{
...
}
#define f f_real_name
int g(void)
{
// call f()
}
#undef f
// calling f() now won't work
Another way, if you can guarantee that f() and g() are the only functions in the file, is to declare f() as static.
EDIT: Another macro trick to cause compiler errors:
static int f(void) // static works for other files
{
...
}
int g(void)
{
// call f()
}
#define f call function
// f() certainly produces compiler errors here
Put g() and f() in the same module, and declare f() as static. The static keyword makes f() available only to functions in the same module, or source file.
You might also want to mention that no other methods should be allowed in the module with f() and g(), otherwise they could call f().
PS - I really think Chris Lutz' answer is actually the best. It mentions this approach, but also a clever macro renaming that works with fewer environmental conditions (does not require the module file specifically for these two functions).
Note also that with a macro, you could do the following:
#define f() f_should_not_be_called_by_anything_except_g
Which would present a nice error message, and auto-completers (like Visual Studio) would show that tip when the user types f().
You can make module-private functions with the static keyword:
static void func(void)
{
// ...
}
Then, func() can only be called by other functions defined in the same file (technically, the same translation unit: other functions whose definitions are included by a #include directive can still access it). func is said to have internal linkage. All other functions (that is, without the static keyword) are said to have external linkage.
Beyond that, no, there is no way to make functions inaccessible. You can use macros to change the name of the function, but other code can always still access it with the appropriate name.
Place f() and g() in the same source file, declare f() static.
An option for GCC is to use nested functions. While it's not standard C, it works quite well.
It is only possible coincidentally.
If functions f() and g() are both in the same source file, and there are no other functions in the file, and if g() never returns the function pointer to f() to any of its callers, then making f() static will do the job.
If other functions must appear in the same source file, placing f() at the bottom of the file as a static function, and only defining g() immediately after it would achieve more or less the same effect - though if you didn't tell the compiler to generate errors on 'missing declarations' other functions could call it with warnings.
#include <stdio.h>
extern void g(void); /* in a header */
/* Other functions that may not call f() go here */
static void f(void)
{
puts("X");
}
void g(void)
{
f();
}
Clearly, this technique cannot be extended reliably to another pair of functions in the same file - x() and y() - such that x() and only x() can call y() while g() and only g() can call f() at the same time.
However, normally you would rely on the programmers' discipline and simply make f() static in the source file, along with a comment that only g() may call it, and then discipline anyone who modifies the code so that a function other than g() calls f().
You could implement f() as a macro and let the pre-compiler handle it:
#include <stdio.h>
#define f(s) printf("Hello %s!\n", s);
void g(char * w) {
f(w);
}
#undef f
int main(void) {
/* f() calls will produce an undefined reference to 'f' linker error */
g("World");
return(0);
}
In this way, there is no other exposed function and no need for a static function.
Related
below is my code:
//main.c
//I'm not using header file here,I know it is bad practice, it is just for demo purpose.
int main()
{
func();
return 0;
}
//test.c
void func()
{
...
}
we can see that above code compiles and can be linked by linker, but the same thing doesn't apply to variables as:
//main.c
int main()
{
sum += 1;
return 0;
}
//test.c
int sum = 2020;
then this code won't compile and can't be linked, and we have to add extern int sum; before main function in main.c.
But why we don't need to add extern in main.c as:
//main.c
extern void func(); //or `void func();` since functions are by default external
// without above line, it still compile
int main()
{
func();
return 0;
}
is it a little bit inconsistent here?
Note: by saying " Functions are by default external.",my understanding is: we can save some keystokes without typing extern , so void func(); == extern void func();, but we still need to add void func(); before main function in main.c, isn't it?
Both programs are incorrect since C99 and may be rejected by the compiler. An identifier may not be used in an expression without previously being declared.
In C89 there was a rule that if you write something that resembles a function call, and the function name has not previously been declared, then the compiler inserts a function declaration int f(); . There was not a similar rule for use of other identifiers that aren't followed by parentheses.
Some compilers (depending on compiler flags) will, even if set to C99 or later mode, issue a diagnostic and then perform the C89 behaviour anyway.
Note: your program still causes undefined behaviour in C89 because the implicit declaration is int func(); but the function definition has void func() which is incompatible type.
The compiler doesn't need to know anything about a function, in order to generate code to call it. In the absence of a prototype, it might generate the wrong code, but it can generate something (in principle, at least -- standards-compliance might forbid it by default). The compiler knows the calling convention for the platform -- it knows to put the function arguments onto the stack or into registers as required. It knows to write a symbol that the linker can later find and fix up, and so on.
But when you write "sum++", the compiler has no clue, lacking a declaration, how to generate code for that. It doesn't even know what kind of thing "sum" is. The code needed to increment a floating-point number will be completely different to that needed to increment an integer, and may be different from that needed to increment a pointer. The compiler doesn't need to know where "sum" is -- that's the linker's job -- but it needs to know what it is, to produce meaningful machine code.
But we don't need to add extern for the function in main.c as extern void func(); or void func();(as functions are implicitly extern prefixed) and the code still compile?
That's correct. Functions are by default external.
To make functions specific to a local source file (translation unit), you need to specific static for them.
Variables, on the other hand, are visible in the source file only. If you want to make some variable visible outside the source file where it is defined, you need extern for it.
There are two completely different topics - function prototypes and linkage.
void foo(void);
provides the extern function prototype needed by compiler to know the number and type of parameters and the type of the return value. Function has an external linkage - ie can be accessed by other compilation units
static void foo(void);
provides the static function prototype. Function has an no external linkage - ie it cannot be accessed by other compilation units
By default functions have an external linkage.
Objects (global scope).
int x;
Defines the object x having the external linkage and type int.
If you define another x object in another compilation unit the linker will complain and emit an error.
extern int x;
Only declares the object x without defining it. The object x has to be defined in other compilation unit.
Files: A(main), B
I have learned that B's function can't be use in A without
funcntion definitions.
But my code ran normally with A, B files without function definitions
This is my code:
B.c
void a()
{
printf("hi");
}
A.c
#include <stdio.h>
void main()
{
a();
}
What is it? I'm confused.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
addendum...
sorry for my bad question.
my code works well with error.
but i couldn't see error.
but i have more question for difference between
'void a();'
'extern void a();'
Once upon a time, C did not require prior declaration of all functions. Many compilers still let you get away with this.
In file A.c, when you called
a();
where a was a function the compiler has never seen before, the compiler assumed that the declaration
extern int a();
was in scope. That is, the compiler assumed that a was a function taking unspecified arguments and returning int.
Or, that used to be the rule. That rule is no longer in C, so yes, you are supposed to explicitly declare all your functions before you call them. Most of today's compilers will warn you when they apply the old rule, and many aren't willing to apply the rule at all, or at least, not unless you use a non-default option flag requesting them to. But it sounds like your compiler is still willing to apply the rule without warning or error. That's great if you're compiling a bunch of very old code, but it's not so great if you're trying to learn modern C.
Now, in this case you have the additional problem that the actual definition of function a in file B.c defines it as returning void, not int, so theoretically that's wrong, too. But, in practice, the error of misdeclaring (or mis-calling) void- versus int-returning functions is an innocuous one, that doesn't cause any real problems. (It's still wrong, though, and worth avoiding.)
I think you know this, but a correct setup would either be to have file A.c look like this:
#include <stdio.h>
extern void a(void);
int main()
{
a();
}
or else to create the file B.h containing
extern void a(void);
and then to have file A.c look like this:
#include <stdio.h>
#include "B.h"
int main()
{
a();
}
(Note that I have also changed void main() to int main(), for correctness. If you're using an old compiler, as it sounds like you are, you may also have to add the line return 0; at the end of main().)
Addendum. You had also asked about that extern keyword. It has to do with the distinction between declarations and definitions. But this distinction plays out slightly differently for functions, versus global variables.
Declarations explain what type something has. Definitions explain what type something has, and they additionally allocate memory for the something, and supply its initial value.
These are declarations:
extern int i;
int f(int);
extern int f2(int, double);
These are definitions:
int i;
int i2 = 2;
int f(int x) { return 2 * x; }
int f2(int n, double x) { return n * x; }
The keyword extern explicitly says, "This is a declaration, the definition is somewhere else." For global variables, this makes a big difference. But for functions, when you say int f(int);, the compiler can tell, when it finds a , instead of a {, that this is a declaration (not a definition), so the keyword extern is optional in function declarations.
(Also, functions are always global in C; there are no local functions.)
See also section 4.2 and section 4.3 of these course notes.
I am working on an embedded project and in the source code of the project (which is in C) contains a function which is used to check whether the ethernet type is polling or interrupt.
We have a function as below
unsigned char mode(void);
unsigned char xmode(void)
{
if(mode())
return 1;
return 0;
}
The function mode() does not have a body. What will happen when the function mode() is called by the function xmode() ?
To extend on the previous answers.
That isn't an "empty" function, it is a prototype.
The compiler uses this to output object code for the functions you have the body for. It needs to be able to set up the function call properly and make sure it handles any conversions and the like. The object code will contain references to the function and the linker will replace these references with the correct value.
It also means that the compiler can do error checking for you and get more information than the linker could. Fun fact, the C standard used to allow implicit declaration of functions.
(This is simplified, for clarity.)
In the above code unsigned char mode(void); tells the compiler that the function mode() exist and it doesn't take any arguments but returns an unsigned char.
This doesn't really define the function. It only defines the way to call it. This thing is called a function prototype.
The function mode() is defined either later in this same file or in another file (possibly an assembly file).
One of the common uses of function prototypes is to implement recursion.
Consider functions a() and b(), each calling the other one, and defined in the same file:
void a()
{
b();
}
void b()
{
a();
}
When the compiler sees b() inside of a(), it does not have a slightest idea of what b() really is or what it's supposed to be. Obviously, if you change the order in which you define a() and b(), you will have the same problem, but now a() won't be known inside of b().
To fix that, you add a prototype:
void b();
void a()
{
b();
}
void b()
{
a();
}
Now the compiler will know what b() is (a function) and know how to call and use it.
This will either fail to link, or else there is a file that you're linking with that contains the actual mode() function.
Is it possible to put the variable declarations in an external function? After reading from Wikipedia that:
an inline function is a function upon which the compiler has been requested to perform inline expansion. In other words, the programmer has requested that the compiler insert the complete body of the function in every place that the function is called, rather than generating code to call the function in the one place it is defined.
I hypothesized that the following might work. It did not take long for the compiler to slap my fingers :(
inline void declaration(){
int a;
}
int main(){
declaration();
a=2;
return 0;
}
This may not be how it is done but if you want a basic idea of how you can think about what happens when you inline a function.
Imagine the compiler turning your code into something like this, then you see why it will not work.
int main(){
{
int a;
}
a=2;
return 0;
}
The call to declaration() is replaced by the contents of the function including brackets, thus int a; is declared in an inner scope and is not visible in the main function.
No, this is not possible.
What is possible, is to use a preprocessor directive #define:
#define VARBLOCK int a, b, c; char ca, cb, cc;
int main()
{
VARBLOCK;
a = 2;
}
This would be a bad practice. Also these would still be variables only available in the scope of function where it were placed, without values being shared.
No - as far as I'm aware an inline function must behave semantically equivalent to a non-inline function; it doesn't affect what counts as legal code. It's just an optimization.
In particular, you could have a variable called a in both functions, but they'd be separate variables on the stack.
(Even if you could do this, I'd suggest it would be a very bad idea in terms of readability.)
inline functions are usually just a function containing no more than about 4 lines and you would want the compiler to do the optimization you where talking about since it would be faster to do what the function does, rather than adding extra code.
Inline expansion is used to eliminate the time overhead when a function is called. It is typically used for functions that execute frequently.
So there's nothing special with the inline function, rather than it might be handled differently by the compiler. They don't share their stack with any other function, which would be the only way for main to use a variable that is created in a different scope.
So my tip is; write your functions, and treat them as you usally should. Then when you are done, inline the short ones that you use a lot.
And if you really wanna create a variable in another function, allocate it on the heap in the function and return a pointer that you save and then set to 2 (your case). :) Just remember to free the memory!
You can do this, though:
#include <stdio.h>
int* GetMyIntAddress(void)
{
static int blah = 0;
return &blah;
}
int main(void)
{
printf("%d\n", *GetMyIntAddress());
*GetMyIntAddress() = 123;
printf("%d\n", *GetMyIntAddress());
return 0;
}
blah will be a global variable defined in the scope of the GetMyIntAddress() function.
If you add inline to the definition of GetMyIntAddress(), you are risking to get multiple independent instances of blah if the inline function is used in different modules (e.g. included from a shared header file).
Does the order in which C objects appear on the file matter?
For example, in functions, if I create two functions and the one above references the other one will it work? (Yes it will, I've tried it.)
Is the same in effect for static functions, INLINE functions, etc.?
Is the same in effect for structs? What happens if I reference a struct which is defined further down on the .c file?
Is this to any extend compiler-specific? How does the compiler work in this case? Does it first scan the whole file for all declarations/definitions and then attempts to dereference functions/symbols?
First, if by "if I create two functions and the one above references the other one will it work?" you mean something like this:
int foo()
{
return bar();
}
int bar()
{
return 0;
}
Then the compiler may do educated guesses at what bar() is, but it will at least spit a warning if bar() wasn't already declared. For symbols that can't be called (like variables or types), it's an outright error if they're used before they're declared.
In C, whenever you use an identifier (and no matter the kind of the identifier: it may be a function, a variable, a type, etc.), it should be declared beforehand. The various modifiers you may add to any identifier (like you said, static, inline and all the others) have no impact on this.
Do not confuse declaration and definition. A declaration is just telling the compiler that a name exists; a definition actually tells the compiler what it is.
For instance, this is a definition:
int bar() { return 4; }
Notice how it has a body, with (simple) code inside.
This is the matching declaration:
int bar();
The compiler will gladly accept the use of a function as soon as it sees either the declaration or the definition for it. For organization reasons and better flexibility, it's often better to write declarations for all your functions at the top of your C file (or inside an included header file) then the definitions.
So, my first example should look like this:
int foo();
int bar();
int foo()
{
return bar();
}
int bar()
{
return 0;
}
With the declarations above the C code, I can change the order of the functions in any way I like.
Typically something must be defined above where you use it. You can avoid this in different ways for different situations.
For functions, just provide a prototype above where it's called and all will be well.
int trol(int a, int b);
// use trol(int, int)
int trol(int a, int b) { }
If you have two functions, a and b, and they call each other and are defined in the order of: a, b, then you must provide b's prototype above the definition of a. a's prototype is not required because it is defined above where it is used inside b. Then the compiler will have no problems.
One other special case for functions is that you can use a function without declaring it and the compiler will try to infer the signature from the call. This answer explains it pretty well I think: Must declare function prototype in C?
For structs, you can use pointers to them before they are actually defined (but you can't access any of the fields) by providing a forward declaration:
struct s;
// use s*'s
struct s { };
(The above scenario facilitates recursive data structures like linked lists and trees; you can use pointers to structs before they are fully defined because the size of any type of pointer is constant.)
It matters, because if the compiler doesn't know what the function is - it will try to 'guess' (create a default int foo() prototype with matching parameters), and if your call is incorrect - you'll have mismatches (build errors, implicit castings, whatever).
It is common practice (if not even required) to declare the function before calling it (through prototypes aka forward declarations).
For functions with variable parameter lists (like printf) you must have a forward declaration for them to work properly. For example this code will not compile:
int foo(int a)
{
b(a);
b("hello", "kitty");
}
void b(int a, ...)
{
printf("%d", a);
}
But this - will:
#include <stdio.h>
int foo(int a)
{
return b(a);
}
int b(int a)
{
return printf("%d", a);
}
(with warning about the implicit forward declaration)
So in order to avoid dealing with the order of the objects in the file - use prototyping (forward declarations) to let the compiler know what's following.
From my experience, everything in C has to be written with the referenced "object" before the reference is made. I don't think this is specific to any compiler, but maybe there are some which I haven't found. Basically, everything always has to be:
Object Declaration
...
Object Reference