Why can I call a function in C without declaring it but not in C++? - c++

In C++, it is a compiler error to call a function before it is declared. But in C, it may compile.
#include<stdio.h>
int main()
{
foo(); // foo() is called before its declaration/definition
}
int foo()
{
printf("Hello");
return 0;
}
I have tried and know that it is correct but I can't get the reason behind it. Can anyone please explain how the compilation process actually takes place and differs in both the languages.

The fact that the code "compiles" as a c program doesn't mean you can do it. The compiler should warn about implicit declaration of the function foo().
In this particular case implicit declaration would declare an identical foo() and nothing bad will happen.
But suppose the following, say this is
main.c
/* Don't include any header, why would you include it if you don't
need prototypes? */
int main(void)
{
printf("%d\n", foo()); // Use "%d" because the compiler will
// implicitly declare `foo()` as
//
// int foo()
//
// Using the "correct" specifier, would
// invoke undefined behavior "too".
return 0;
}
Now suppose foo() was defined in a different compilation unit1 foo.c as
foo.c
double foo()
{
return 3.5;
}
does it work as expected?
You could imagine what would happen if you use malloc() without including stdio.h, which is pretty much the same situation I try to explain above.
So doing this will invoke undefined behavior2, thus the term "Works" is not applicable in the understandable sense in this situation.
The reason this could compile is because in the very old days it was allowed by the c standard, namely the c89 standard.
The c++ standard has never allowed this so you can't compile a c++ program if you call a function that has no prototype ("declaration") in the code before it's called.
Modern c compilers warn about this because of the potential for undefined behavior that can easily occur, and since it's not that hard to forget to add a prototype or to include the appropriate header it's better for the programmer if the compiler can warn about this instead of suddenly having a very unexplicable bug.
1It can't be compiled in the same file because it would be defined with a different return type, since it was already implicitly declared
2Starting with the fact that double and int are different types, there will be undefined behavior because of this.

When C was developed, the function name was all you needed to be able to call it. Matching arguments to function parameters was strictly the business of the programmer; the compiler didn't care if you passed three floats to something that needed just an integer.
However, that turned out to be rather error prone, so later iterations of the C language added function prototypes as a (still optional) additional restriction. In C++ these restrictions have been tightened further: now a function prototype is always mandatory.
We can speculate on why, but in part this is because in C++ it is no longer enough to simply know the function name. There can be multiple functions with the same name, but with different arguments, and the compiler must figure out which one to call. It also has to figure out how to call (direct or virtual?), and it may even have to generate code in case of a template function.
In light of all that I think it makes sense to have the language demand that the function prototype be known at the point where the function is called.

Originally, C had no function prototypes, and C++ did not exist.
If you said
extern double atof();
this said that atof was a function returning double. (Nothing was said about its arguments.)
If you then said
double d = atof("1.3");
it would work. If you said
double d2 = atof(); /* whoops, forgot the argument to atof() */
the compiler would not complain, but something weird would happen if you tried to run it.
In those days, if you wanted to catch errors related to calling functions with the wrong number or type of arguments, that was the job of a separate program, lint, not the C compiler.
Also in those days, if you just called a function out of the blue that the compiler had never heard of before, like this:
int i = atoi("42");
the compiler basically pretended that earlier you had said
extern int atoi();
This was what was called an implicit function declaration. Whenever the compiler saw a call to a function whose name it didn't know, the compiler assumed it was a function returning int.
Fast forward a few years. C++ invents the function prototypes that we know today. Among other things, they let you declare the number and types of the arguments expected by a function, not just its return type.
Fast forward a few more years, C adopts function prototypes, optionally. You can use them if you want, but if you don't, the compiler will still do an implicit declaration on any unknown function call it sees.
Fast forward a few more years, to C11. Now implicit int is finally gone. A compiler is required to complain if you call a function without declaring it first.
But even today, you may be using a pre-C11 compiler that's still happy with implicit int. And a C11-complaint compiler may choose to issue a mere warning (not a compilation-killing error) if you forget to declare a function before calling it. And a C11-compliant compiler may offer an option to turn off those warnings, and quietly accept implicit ints. (For example, when I use the very modern clang, I arrange to invoke it with -Wno-implicit-int, meaning that I don't want warnings about implicit int, because I've still got lots of old, working code that I don't feel like rewriting.)

Why can I call a function in C without declaring it?
Because in C, but not in C++, a function without a prototype is assumed to return an int. This is an implicit declaration of that function. If that assumption turns out to be true (the function is declared later on with return-type of int), then the program compiles just fine.
If that assumption turns out to be false (it was assumed to return an int, but then actually is found to return a double, for example) then you get a compiler error that two functions cannot have the same name. (eg. int foo() and double foo() cannot both exist in the same program)
Note that all of this is C only.In C++, implicit declarations are not allowed. Even if they were, the error message would be different because C++ has function overloading. The error would say that overloads of a function cannot differ only by return type. (overloading happens in the parameter list, not the return-type)

Related

parameter dropping when using C linkage in a C++ program

I have the following code in main.cpp
extern "C"
{
void bar(int x, char* s);
}
int main()
{
bar(5, "hello");
}
Notice that function bar is declared as taking two arguments. This is then compiled and linked to a static library bar.cpp that contains this code
#include <iostream>
extern "C"
{
void bar(int x)
{
std::cout << x;
}
}
Notice function bar takes only one argument.
The executable compiles successfully and prints 5
I have three questions:
Shouldn't there have been a compiler error indicating the mismatch in the number of parameters?
In the scenario above, since the string hello is not received by bar, when and how is it destroyed?
Is it completely valid to write and use code as above (knowing parameters will be dropped)? What exactly are the semantics behind parameter dropping?
Although your specify VS, the question is more generally answered about C++, compilers, and execution platforms in general.
1.) You instructed the compiler to follow the C style calling convention for your platform to reference a symbol not defined in that compilation unit. The compiler then generates an object which tells the linker "call _bar here" (may be bar depending on your platform), which happily resolves to the compilation output of bar.cpp. The older C++ calling conventions would result in mangled names like barZ8intZP8char or worse depending on your compiler, to ensure overloading worked properly. However newer compilers are possibly smarter (magic!) and may understand additional metadata stored in the object file.
A bigger issue for multi-platform code is concerned with stack ordering. On a few platforms parameters are stored in reverse order on the stack than their declaration, thus your code would then be provided with the address of the string instead of the integer value. Fine for printing an integer, but would result in (hopefully) a segfault with the first parameter being a string and the second being an integer in the function declaration.
2.) This depends on the platform you are using. For most platforms related to the IA32 systems (x86, AMD64, IA64, etc), the caller is responsible for managing the parameters on the stack. Thus the stack frame containing the extra parameter is discarded in full when the call is complete. There are optimization cases where this may trigger a discrete bug where a frame is reused because the compiler was misinformed regarding the call stack.
3.) For application programming I would consider this a bad practice as it may introduce very hard to diagnose bugs. I'm sure some one has found an edge case to that statement regarding binary compatibility; however I would prefer the compiler to be aware of the parameters to avoid the optimization bugs referred to in #2.

Why the error of - calling the function before being declared, is not shown?

main()
{
f();
}
int f( int i, float fl)
{
printf("function");
}
Why does the above code runs successfully in 'C' and prints function when it should report an error, as f () is being called before it is declared.
When it's running successfully in 'C', then why not in 'C++'. When running in c++ it's showing: error: 'f' was not declared in this scope
If it is because of something like the compiler assumes an undeclared function to return an int and accept an unspecified number of arguments, then why does it runs successfully for the function below too ( i.e. when returning the returning type to void instead of int ?
void f ( int i, float fl)
{
printf("function");
}
Old versions of the C programming language permitted function references without earlier declarations. As a legacy, many current compilers still support the old language or aspects of it. This is why some compilers accept the source code you have shown. Your compiler likely has switches that tell it to use a more recent version of the C programming language or to be more strict about adherence to the standard.
C++ was developed more recently and does not have the legacy of functions without declarations.
The different return types work because the assembly language happens to be implemented the same way. For a function returning void, the called routine simply performs its operations and returns. For a function returning int, the called routine performs its operations, puts its final result in a specific processor register, and returns. In the calling routine, when the return value of a function returning int is not used, the calling routine simply ignores what is in the processor register. Because the register is ignored, there is no difference, to the calling routine, between a function returning void and a function returning int. This will not be the case on all target platforms; there can be differences between functions with different return types, especially when the return types are more complicated objects (such as structs). And, if the calling function did use the return value, the return type would make a difference. The function returning void would leave some uncontrolled value in the processor register where a return value is supposed to be, and the calling function would use that and get unexpected results.
As should be apparent, none of this is behavior you should rely on. It is good practice to use the compiler switches that specify you would like stricter adherence to the standard and would like more warnings. (I would prefer these be the default for compilers.) And it is good practice to write code that conforms to the standard.
Because C allows the implicit declaration of functions. Or at least
it did; C90 may require a declaration, I'm not sure. But since not
declaring functions was common practice in C for such a long time, I
would expect most compilers to continue to allow it, even after it is
banned.
Because C and C++ are different languages. C++ has never allowed
implicitly declaring functions.
Because historically, C didn't have a void type; functions with no
return value were declared int, even if they didn't return anything,
and there's no problem as long as you don't attempt to use the
(non-existant) return value.
The error does not show in C because you're not using the proper flags in the invocation of your compiler.
What is your compiler?
If it's gcc, try gcc -std=c99 -pedantic -Werror ...

Stopping Compiler from generating errors in a C++ code that has legacy C code

I am porting a legacy C program to C++. However, the compiler is not happy and requires additional typecastings for C++. For example, I have this function...
void foreach_element_in_patch(Patch *patch, void (*func)(),
long arg1, long process_id);
In the original C Code, it is used like this...
foreach_element_in_patch( patch, display_interactions_in_element,
mode, process_id );
However, for C++ I need to typecast the second argument to stop the compiler from gernerating an error.
foreach_element_in_patch( patch, (void (*)())display_interactions_in_element,
mode, process_id );
The error generated by the compiler is the following...
invalid conversion from ‘void (*)(Patch*, long int, long int)’ to ‘void (*)()’
Now is there a way to ask the compiler not to generate errors for such things. I have tried prefixing this function with extern "C" but still the C++ compiler is not happy. My applications is loaded with such code and I do not have the time to adjust so much code.
The error is quite clear, and your cast is invalid. You can't use a function that takes arguments as a function that doesn't take arguments.
For your code to work, you need to either:
Create a new function that calls display_interactions_in_element with sensible defaults.
Or use a capture-less and argument-less lambda that does the same (it might not be supported by your compiler, yet, though).
Note that if your code tries to call that function as if it took arguments later, it means the code is fundamentally broken.
Yes, there is a way. Compile your code as C.
C++ has stricter type safety rules, and requires you to explicitly cast types that could be implicitly converted in C.
So either compile the code as C, or make the modifications necessary for the code to be valid C++, and compile it as C++.
You should be able to compile your C files as C, your C++ files as C++, and then link them together without a problem.
But when you try to compile your C files as C++, the compiler is going to tell you if your code isn't valid C++.
I think your error comes from the fact that the function signature is has a different meaning in C and C++. The second parameter specification
void (*func)()
in C means "a function with an unknown number and type of parameters" and in C++ it means "a function without arguments". So these are quite different and it must crash.
The error is not in the lack of type safety of C, but in your code. Don't do that. Use strict prototypes, even in C. The correct parameter specification for both languages is just
void (*func)(Patch*, long int, long int)
that's it and everything is just blindly hacking around.
The easiest thing to do is to change the function prototypes and headers to declare the correct type of function pointer. So for example, for
void foreach_element_in_patch(Patch *patch, void (*func)(),
long arg1, long process_id);
I just need to change it to
void foreach_element_in_patch(Patch *patch, void (*)(Patch*, long int, long int),
long arg1, long process_id);
Instead of making changes at every function call.

calling qsort with a pointer to a c++ function

I have found a book that states that if you want to use a function from the C standard library which takes a function pointer as an argument (for example qsort), the function of which you want to pass the function pointer needs to be a C function and therefore declared as extern "C".
e.g.
extern "C" {
int foo(void const* a, void const* b) {...}
}
...
qsort(some_array, some_num, some_size, &foo);
I would not be surprised if this is just wrong information, however - I'm not sure, so: is this correct?
A lot depends on whether you're interested in a practical answer for the compiler you're using right now, or whether you care about a theoretical answer that covers all possible conforming implementations of C++. In theory it's necessary. In reality, you can usually get by without it.
The real question is whether your compiler uses a different calling convention for calling a global C++ function than when calling a C function. Most compilers use the same calling convention either way, so the call will work without the extern "C" declaration.
The standard doesn't guarantee that though, so in theory there could be a compiler that used different calling conventions for the two. At least offhand, I don't know of a compiler like that, but given the number of compilers around, it wouldn't surprise me terribly if there was one that I don't know about.
OTOH, it does raise another question: if you're using C++, why are you using qsort at all? In C++, std::sort is almost always preferable -- easier to use and usually faster as well.
This is incorrect information.
extern C is needed when you need to link a C++ library into a C binary; it allows the C linker to find the function names. This is not an issue with function pointers (as the function is not referenced by name in the C code).

Shouldn't you always need to define functions before using them in a C file?

I have the following bit of C code:
int main() {
myFunctionABC(2);
return 0;
}
void myFunctionABC(int n) {
printf("%d\n", n);
}
So... this code is working and I don't understand why. I always thought that a C compiler would always need every referred function to be already "known", otherwise would fail the compilation process.
Why is this working?
There has never been any requrement to define functions before calling them in C or in C++ (as the title of your question suggests). What is required in C++ and C99 (and in some cases in C89/90) is to declare functions before calling them.
As for your code... Your code is not "working". The best you can hope for is that your code will produce undefined behavior that will just happen to resemble "working".
Firstly, the code will not even compile as C++ or as C99 (and you tagged your question as both C and C++). C++ and C99 unconditionally require functions to be declared before they are called.
Secondly, with C89/90 compiler the code might compile, but will produce the aforementioned undefined behavior anyway. Even in C89/90 calling variadic functions (like printf) without declaring them first is illegal - it produces undefined behavior.
For non-variadic functions calling them without declaring them is OK - the implicit declaration rules of C89/90 will take care of that. But these rules will make the compiler to conclude that your undeclared myFunctionABC function returns an int, while in reality you defined it as returning void - this discrepancy leads to undefined behavior as well. Most self-respecting compilers will at least warn you about the problem.
gcc rightfully complains:
make 4356180
4356180.c:6: warning: conflicting types for ‘myFunctionABC’
4356180.c:2: note: previous implicit declaration of ‘myFunctionABC’ was here
If I add -Wall, I get these at well:
make CFLAGS=-Wall 4356180
4356180.c: In function ‘main’:
4356180.c:2: warning: implicit declaration of function ‘myFunctionABC’
It is not erroneous to declare a function prototype before actually calling it even if its definition is in a subsequent location, but it is a good practice to help the compiler out, check this similar post