For reasons out of my control, I have to implement this function in my C code:
double simple_round(double u)
{
return u;
}
When this function is called, is it ignored by the compiler, or does the call take place anyway? For instance:
int y;
double u = 3.3;
y = (int)simple_round(u*5.5); //line1
y = (int)u*5.5; //line2
Will both lines of code take the same time to be executed, or will the first one take longer?
Because the function is defined in a different C file from where it's used, if you don't use link-time optimization, when the compiler calls the function call it won't know what the function does, so it will have to actually compile the function call. The function will probably just have two instructions: copy the argument to the return value, then return.
The extra function call may or may not slow down the program, depending on the type of CPU and what else the CPU is doing (the other instructions nearby)
It will also force the compiler to consider that it might be calling a very complicated function that overwrites lots of registers (whichever ones are allowed to be overwritten by a function call); this will make the register allocation worse in the function that calls it, perhaps making that function longer and making it need to do more memory accesses.
When this function is called, is it ignored by the compiler, or does the call take place anyway?
It depends. If the function definition is in the same *.c file as the places where it's called then the compiler most probably automatically inlines it, because it has some criteria to inline very simple functions or functions that are called only once. Of course you have to specify a high enough optimization level
But if the function definition is in another compilation unit then the compiler can't help unless you use link-time optimization (LTO). That's because in C each *.c file is a separate compilation unit and will be compiled to a separate object (*.o) file and compilers don't know the body of functions in other compilation units. Only at the link stage the unresolved identifiers are filled with their info from the other compilation units
In this case the generated code in a *.c file calls a function that you can change in another *.c file then there are many more reliable solutions
The most correct method is to fix the generator. Provide evidences to show that the function the generated code calls is terrible and fix it
In case you really have no way to fix the generator then one possible way is to remove the generated *.c file from the compilation list (i.e. don't compile it into *.o anymore) and include it in your own *.c file
#define simple_round(x) (x)
#include "generated.c"
#undef simple_round
Now simple_round() calls in generated.c will be replaced with nothing
If the 'generated' code has to be compiled anyway, perhaps you can 'kludge' a macro, Macro, that redefines the call to the 'inefficient' rounding function made by that code.
Here's a notion (all in one file). Perhaps the #define can be 'shimmed in' (and documented!) into the makefile entry for that single source file.
int fnc1( int x ) { return 5 * x; }
void main( void ) {
printf( "%d\n", fnc1( 5 ) );
#define fnc1(x) (x)
printf( "%d\n", fnc1( 7 ) );
}
Output:
25
7
Related
I have a function whose behavior may need to be modified based on the file it is called from (e.g., to increase debugging trace output). This modification would need to be done without recompiling (e.g., by editing a configuration file or changing an environment variable).
Just as an example that would fill this need, I could write Function() as:
FunctionModifiable( const char* pszFile, int i );
Then make a macro thusly:
#define Function( i ) FunctionModifiable( __FILE__, (i) )
And FunctionModifiable() would have the duty to check pszFile in say an unordered_set<> that was populated during initialization to see if special functionality need be activated.
However, the overhead of that search is a minus (this is high-performance software and the function is called a huge number of times), and there is some per-file data that would need to be cached in this situation. We can eliminate the search, and have get storage for the cached info, by passing in not __FILE__ but a pointer to a helper object. This object needs the filename so that, when it undergoes one-off initialization, it can consult config or environment variables or what have you to know whether it needs special handling.
FunctionHelperObject fho( __FILE__ );
#define Function( i ) FunctionModifiable( &fho, (i) ) // C-style solution
#define Function( i ) fho.MethodModifiable( (i) ) // C++-style solution
OK, now say I want to avoid users having to define that fho in every file. (Inter alia, we can't re-write all existing files calling Function(), though say we're willing to recompile them).
The idea I had was the unusual step of putting a variable definition in the header file, so that any program including the header for Function() would get a FunctionHelperObject fho( __FILE__ ) for free. (Such definition would be #pragma once or guarded by a preprocessor variable.
The problem is that __FILE__ at that point would be the name of the header, not of the top-level compilation unit. If there was a __CFILE__ symbol, that would be the solution, but there's not.
Ultimately the best I can think of has shortcomings: 1) the "modifiable" aspect would only be available in source code explicitly written to use it, and 2) you'd have to do that explicit writing, and 3) starting to get a little complicated. In code you want to add the ability to modify behavior to you'd write USE_MODIFIABLE_FUNCTION somewhere after including the header in question. That'd be a macro that creates the FunctionHelperObject above, this time in the right "file" so __FILE__ would have the required value, and furthermore defines a macro as seen above that would mask the non-customizable function Function() with one of the two macros seen above. In short: the previous example, plus
#define USE_MODIFIABLE_FUNCTION FunctionHelperObject fho( __FILE__ );\n#define Function( i ) fho.MethodModifiable( (i) )
Code written without USE_MODIFIABLE_FUNCTION would simply call the uncustomizable Function() the normal way.
But surely this is some other accepted, portable way to provide this behavior? Although I've talked exclusively about the C preprocessor, is there perhaps any C++ template magic or any other approach that would work?
Cache the result.
// in the header with Function macro
static FunctionHelperObject functionhelper;
static inline void FunctionModifiableInterface(const char *file, int i) {
static initialized = 0;
if (initialized == 0) {
initialized = 1;
functionhelper = FunctionHelperObject(file);
}
FunctionModifiable(&functionhelper, i);
}
#define Function(i) FunctionModifiableInterface(__FILE__, (i))
You can't predict where the user would want to call you Function(i), so you can't predict the value of __FILE__. Just initialize it on the first call, which also is great, because you will not initialize it if Function is not called. You could do the same initialized check inside FunctionHelperObject constructor.
The really cool and hard to do trick is to modify your build system to allow you to pass a macro with the filename of compiled C file. Because build systems compile one C file at a time, it is possible (and it's a shame compilers doesn't do that by themselves). If you are using cmake with make backend (or really just make by itself), you could do something like this:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__MY_FILE__='\"$(notdir $(abspath $<))\"'")
And then use FunctionHelperObject fho(__MY_FILE__) like you wanted to, because __MY_FILE__ depends only on the output filename from make.
One option is something like this (rough example, keeping the C++ syntax from the OP) :
#define Function(i) do { \
static FunctionHelperObject obj(__FILE__); \
FunctionModifiable(&obj, (i)); \
} while (0)
Note the above will have to be modified to accommodate for a return value if the function has one.
Also : an alternative to __FILE__ might be __func__ if that fits better with your needs.
I just realized when I define a function in C and use it, I can either use it and define the function later or define it and use it later. For example,
int mult (int x, int y)
{
return x * y;
}
int main()
{
int x;
int y;
scanf( "%d", &x );
scanf( "%d", &y );
printf( "The product of your two numbers is %d\n", mult( x, y ) );
}
and
int main()
{
int x;
int y;
scanf( "%d", &x );
scanf( "%d", &y );
printf( "The product of your two numbers is %d\n", mult( x, y ) );
}
int mult (int x, int y)
{
return x * y;
}
will both run just fine. However, in Python, the second code will fail since it requires mult(x,y) to be defined before you can use it and Python executes from top to bottom(as far as I know). Obviously, that can't be the case in C since the second one runs just fine. So how does C code actually flow?
Well, the second code is not valid C, strictly speaking.
It uses your compiler's flexibility to allow an implicit declaration of a function, which has been disallowed in C standard.
The C11 standatd explicitly mentions the exclusion in the "Foreword",
Major changes in the second edition included:
...
remove implicit function declaration
You have to either
Forward declare the function.
Define the function before it's usage (like snippet 1).
Enable the warning in your compiler and your compiler should produce some warning message to let you know about this problem.
As others have noted, routines should be declared before they are used, although they do not need to be defined before they are used. Additionally, older versions of C allowed some implicit declaration of routines, and some compilers still do, although this is largely archaic now.
As to how C is able to support the calling of functions before they are defined, C programs are first translated into some executable format, after which a program is executed.
During translation, a C compiler reads, analyzes, and processes the entire program. Any references to functions that have not yet been defined are recorded as things that need to be resolved in the program. In the process of preparing a final executable file, a linker goes through all of the processed data, finds the function definitions, and resolves the references by inserting the addresses (or other information) of the called routines.
Most commonly, a C compiler translates source code into an object module. The object module contains machine-language instructions for the program. It also contains any data for the program that is defined in the source code, and it contains information about unresolved references that the compiler found while analyzing the source code. Multiple source files may be translated separately into multiple object modules. Sometimes these translations are done by different people at different times. A company might produce a software library which is the result of translating their source files into object modules and packaging them into a library file. Then a software developer would compile their own source files and link the resulting object modules with the object modules in the library.
Multiple object modules can be linked together to make an executable file. This is a file that the operating system is able to load into memory and execute.
For second code you should use forward declaration. That means first declare the function so that compiler will know you will be using this function. For now your code is executed as per C compiler flexibility.
Python compiler is not flexible enough so it will fail to compile.
You said both the codes work just fine. Well, it doesn't. The second snippet will show an error in my compiler and if it does compile correctly, it should not be used.
It voids C regulations.
Declaring functions before is helpful when too many user defined functions are needed.
For a large software developed by C, we first declare all the self-defined functions in a separate header file (e.g. myfun.h). After that, once we write a code (e.g. main.c) that uses the functions listed in myfun.h, we have to #include "myfun.h". I'm wondering how it works, because even if I include the function names declared in header file before the main body, the code cannot see the function details in main.c. I guess it will search the library to get the function details...Am I right?
When you say "it will search the library for the function details" you're not far off, but that isn't quite right. A function declaration, i.e.. a function prototype only contains enough information for the compiler to do two things:
First, the compiler will register the function as a known identifier so that it knows what you're taking about when you call it, as opposed to a random string of letters with parentheses (to the compiler, they are essentially the same thing without a function prototype for either - an error).
Second, the compiler uses the function prototype for checking code correctness. Correctness in this sense means that a function call will match the prototype in both arity and type. In other words a function call to int square(int a, int b); will have two arguments, both integers.
The program doesn't "search the library," though. Function names without parentheses are not function calls but rather function's address. Therefore, when you call a function, the processor jumps to the memory location of the function. (This assumes the function has not been inlined.)
Where is this function located though? It depends. If you wrote the function in the same module, i.e... a .c file that got compiled into an object linked with the main.c file into a single executable, then the location of the function will be somewhere in the .TEXT section of the executable. In other words, it's just a slight offset from the main function's entry point. In a huge project this offset won't be so slight, but it will be shorter than the offset of separate objects.
Having said that, if you compiled this hypothetical function into a DLL which you call from your main program, then the function's address will be determined in one of two ways:
Either you will have generated a .lib/.a? (depending on whether you're on Windows or Linux) file containing the function declaration's and addresses, or:
You will use run-time linking where the main program will calculate the function addresses when it loads the .dll/.so into its address space. First, it will determine where to load it. You can set DLL's to have preferred offsets to optimize load time. Otherwise, libraries will start loading from the first segment available and any additional libraries will need their function address recalculated using this new address, hampering initial load times. Once they are loaded into the program's memory though, there shouldn't be any performance hits thereafter.
Going back to the preprocessor, it's important to note two things. First, it runs before any compilation takes place. This is important. Since the program is not really being "compiled" when the preprocessor is doing its thing, macros are not type-safe. (Insert Haskell joke about C "type safety") This is why you don't -or shouldn't- see macros in C++. Anything that can be accomplished with macros in C can be accomplished by const and inline functions in C++, with the added benefit of type safety.
Second, the preprocessor is almost just a search and replace engine. For example, in the following code, nothing happens because the preprocessor if statement evaluates to false, since I never defined anything. The preprocessor removes the code in this section. Remember that since the compiler has not run in earnest yet, this removed code will not be compiled. This fact is usually utilized to implement functions for debugging or logging in debug builds. In release builds the preprocessor definition is then manipulated such that the debug code is not included.
#include <stdio.h>
#include <stdlib.h>
int main()
{
#if TRUE
printf("Hello, World!");
#endif
return EXIT_SUCCESS;
}
In fact, the EXIT_SUCCESS macro I used is defined in stdlib.h, and replaced by 0. (EXIT_FAILURE =1).
Back in the day, the preprocessor was used as duct tape, basically, to compensate for faults in C.
For example, since const values can't be used as array sizes, macros were used instead, like this:
// Not valid C89, possibly even C99
const int DEFAULT_BUFFER_SIZE = 128;
char user_input[DEFAULT_BUFFER_SIZE];
// Legal since the dawn of time
#define DEFAULT_BUFFER_SIZE 128
char user_input[DEFAULT_BUFFER_SIZE];
Another significant use of the preprocessor was for code portability, for example:
#ifdef WIN32
// Do windows things
#elif
// Handle other OS
#endif
One trick was to define a generic function and set it to the appropriate OS-dependent one (Remember that functions without the parentheses represent the function's address, not an actual function call), like this:
void RequestSomeKernelAction();
#ifdef WIN32
RequestSomeKernelAction = WindowsVersion;
#else
RequestSomeKernelAction = OtherOSFunction;
#endif
This is all to say that the code you see in header files follows these same rules. If I have the following header file:
#ifndef SRC_INCLUDES_TEST_H
#define SRC_INCLUDES_TEST_H
int square(int a);
#endif /** SRC_INCLUDES_TEST_H */
And I have this main.c file:
#define SRC_INCLUDES_TEST_H
#include "test.h"
int main()
{
int n = square(4);
}
This program will not compile. The square function will not be known to main.c because while I did include the header file where square is declared, my #define SRC_INCLUDES_TEST_H statement tells the preprocessor to copy all the header file contents over to main except those in the block where SRC_INCLUDES_TEST_H is defined, i.e... nothing.
These preprocessor commands can be nested, and there are several, which I highly recommend you look up, if only for historical or pedagogical reasons.
The last point I will make is that while the C preprocessor has its faults, it was a powerful tool in the right hands, and in fact, the first C++ compiler Bjarne Stroustroup wrote was essentially just a preprocessor.
zero.c:
int sq();
one.c:
int sq(int i) { return i*i; }
two.c:
int sq(int i, int j);
main.c:
int main() {
printf("%d\n",sq());
printf("%d\n",sq(2));
printf("%d\n",sq(2,3));
}
then I compile each file individually and gcc zero.o one.o two.o main.o -o main
./main gives
1
4
4
I'm a little confused as how this would work successfully. what really happens when I call sq() or sq(2) or sq(2,3)
If you want to know what really happens, have gcc output the assembly for main.o and take a look. I think you will find that when you call sq() the arguments are loaded into the base registers on your machine, and then sq(int i) will do a multiply instruction on the first register. If you pass additional arguments they won't have any affect, and if you don't pass any arguments it will just work on whatever value was previously loaded into that register.
zero.c & two.c do not have any function definition. It's only prototype declaration. Thus, it will not create any assembly code having function definition. (hint: compile with gcc -s flag to verify.)
Only two.c has function definition. Thus two.s will have a function sq, which takes the first argument (generally passed on the stack or the first register of the processor, like eax on intel or r0 in arm) & returns its square.
Since you have not given any prototype in main.c, the compiler (.c -> .s) will not complain. It may probably treat it as int sq(...), but I am not sure about it.
Thus, for 3 different inputs:
sq(), sq(2), sq(2,3) will all call to the same function, which is declared in two.c.
Now, the outputs for sq(2) & sq(2,3) are obvious - return square of the first argument passed. The output for sq() will depend on what is on the stack/eax/r0 as seen in sq's stack. Seems that it was 1. hint: run under gdb to verify.
According to the C spec, your code invokes undefined behavior in multiple ways (and possibly more):
Two declarations of the same function in the same scope use different return or argument types/counts
For a call to a function without a function prototype in scope, the number of arguments does not equal the number of parameters
Since this is undefined behavior, you have no way to predict what will happen. The result doesn't even necessarily have to be consistent. If you aren't seeing compile-time warnings/errors for this code, then you need to turn up your compiler's warning level.
Adding a prototype in main.c will probably resolve the compiler's warnings with this code. The linker may still have issues, though, because you have multiple functions with the same name in the same scope and it's not exactly clear which one you want the code to use.
So, I wrote an answer earlier based on what I read in the post. Which was wrong. Here's the correct answer.
zero.c doesn't generate any code. two.c doesn't generate any code.
main.c and one.c are the only files that actually generate code.
Calling a function with one argument, sq(int i) in one.c, with no arguments is undefined behaviour (so "anything can happen", including something resembling what you expect in some cases). Calling with two arguments is also undefined behaviour - again, it will not necessarily "go wrong" when you do this, but you it is not guaranteed to work (or do what you expect) - it could for example just as well return 9 because it puts arguments into registers from the last to first.
How does the compiler know the prototype of sleep function or even printf function, when I did not include any header file in the first place?
Moreover, if I specify sleep(1,1,"xyz") or any arbitrary number of arguments, the compiler still compiles it.
But the strange thing is that gcc is able to find the definition of this function at link time, I don't understand how is this possible, because actual sleep() function takes a single argument only, but our program mentioned three arguments.
/********************************/
int main()
{
short int i;
for(i = 0; i<5; i++)
{
printf("%d",i);`print("code sample");`
sleep(1);
}
return 0;
}
Lacking a more specific prototype, the compiler will assume that the function returns int and takes whatever number of arguments you provide.
Depending on the CPU architecture arguments can be passed in registers (for example, a0 through a3 on MIPS) or by pushing them onto the stack as in the original x86 calling convention. In either case, passing extra arguments is harmless. The called function won't use the registers passed in nor reference the extra arguments on the stack, but nothing bad happens.
Passing in fewer arguments is more problematic. The called function will use whatever garbage happened to be in the appropriate register or stack location, and hijinks may ensue.
In classic C, you don't need a prototype to call a function. The compiler will infer that the function returns an int and takes a unknown number of parameters. This may work on some architectures, but it will fail if the function returns something other than int, like a structure, or if there are any parameter conversions.
In your example, sleep is seen and the compiler assumes a prototype like
int sleep();
Note that the argument list is empty. In C, this is NOT the same as void. This actually means "unknown". If you were writing K&R C code, you could have unknown parameters through code like
int sleep(t)
int t;
{
/* do something with t */
}
This is all dangerous, especially on some embedded chips where the way parameters are passed for a unprototyped function differs from one with a prototype.
Note: prototypes aren't needed for linking. Usually, the linker automatically links with a C runtime library like glibc on Linux. The association between your use of sleep and the code that implements it happens at link time long after the source code has been processed.
I'd suggest that you use the feature of your compiler to require prototypes to avoid problems like this. With GCC, it's the -Wstrict-prototypes command line argument. In the CodeWarrior tools, it was the "Require Prototypes" flag in the C/C++ Compiler panel.
C will guess int for unknown types. So, it probably thinks sleep has this prototype:
int sleep(int);
As for giving multiple parameters and linking...I'm not sure. That does surprise me. If that really worked, then what happened at run-time?
This is to do with something called 'K & R C' and 'ANSI C'.
In good old K & R C, if something is not declared, it is assumed to be int.
So any thing that looks like a function call, but not declared as function
will automatically take return value of 'int' and argument types depending
on the actuall call.
However people later figured out that this can be very bad sometimes. So
several compilers added warning. C++ made this error. I think gcc has some
flag ( -ansic or -pedantic? ) , which make this condition an error.
So, In a nutshell, this is historical baggage.
Other answers cover the probable mechanics (all guesses as compiler not specified).
The issue that you have is that your compiler and linker have not been set to enable every possible error and warning. For any new project there is (virtually) no excuse for not doing so. for legacy projects more excuse - but should strive to enable as many as possible
Depends on the compiler, but with gcc (for example, since that's the one you referred to), some of the standard (both C and POSIX) functions have builtin "compiler intrinsics". This means that the compiler library shipped with your compiler (libgcc in this case) contains an implementation of the function. The compiler will allow an implicit declaration (i.e., using the function without a header), and the linker will find the implementation in the compiler library because you're probably using the compiler as a linker front-end.
Try compiling your objects with the '-c' flag (compile only, no link), and then link them directly using the linker. You will find that you get the linker errors you expect.
Alternatively, gcc supports options to disable the use of intrinsics: -fno-builtin or for granular control, -fno-builtin-function. There are further options that may be useful if you're doing something like building a homebrew kernel or some other kind of on-the-metal app.
In a non-toy example another file may include the one you missed. Reviewing the output from the pre-processor is a nice way to see what you end up with compiling.