C/C++ definitions of functions - c++

Yesterday, I have been watching discussion here, about compilers and linkers. It was about C library function definitions. I have never thought of that, so it inspired me to do some searching, but I cannot find exactly what I want. I wonder, what is the smallest syntax you need to add into your source code to enable just printf() function. I mean the function declaration from stdio.h you need.

The C99 declaration of printf() is
int printf(const char *restrict, ...);
but most compilers will also accept
int printf(const char *, ...);
See also C99 section 7.1.4, §2:
Provided that a library function can be declared without reference to any type defined in a
header, it is also permissible to declare the function and use it without including its
associated header.
Note: In this case, the restrict qualifier combined with const promises the compiler that the format string is never modified within printf(), even if the pointer is passed again as one of the variadic arguments.

The definition is usually compiled in a shared library. The declaration is what you need. Not having a declaration in scope invokes undefined behavior. So, for every library, you'd typically have a (set of) header file(s) and the compiled binary shared/static library. You compile your sources by including appropriate headers and link with the library. To bring in the declaration in scope use the #include directive. E.g. for printf you'd do:
#include <stdio.h>
int main() {
printf("Hello, world\n");
return 0;
}
But then any decent book on C or C++ should already cover this in detail and with better examples.

It depends on your compiler and platform.
On most cases just declaring
int printf(const char *, ...);
will just do, however, your particular compiler/platform or C library implementation even can change this declaration, for calling convention purposes.
All in all it is not worth it to try and declare things yourself, as this could be a violation of the one definition rule. You should always include the apropriate header, stdio.h(cstdio for C++) in this case.

Related

Prototyping a function - C++

Lately, some of my CPP tutorials have used function prototypes . I understand you must initialize the function, but what is the overall use of it? Couldn't you use just as well write the entire function before main() instead of defining a prototype?
int returnValue(void);
int main()
{
std::cout << returnValue() << std::endl;
return 0;
}
int returnValue(void)
{
return 10;
}
Couldn't you use just as well write the entire function before main() instead of defining a prototype?
I can think of the following cases where you cannot.
Functions used in multiple files
If a function is used in multiple source (.cpp) files, you can define the function only in one source file. You have to declare it in the remaining source files. For convenience and to avoid errors, such declarations are put in header files. The header files are then #included by the source files.
Mutually recursive functions
If foo calls bar and bar calls foo, you cannot implement them without providing a declaration of at least one of the functions.
As a matter of good practice, it's better to declare both functions first. Then you can implement them in any order.
One important usage case is when you separate your implementation from the declarations. In other words, you declare your functions/classes etc in a header file, and define (i.e. implement) them in cpp files. In this way, you can distribute your program with the implementation fully compiled in a shared or static library. In order to use a pre-compiled function you need to introduce it to your program via a declaration. Example:
a.h
void f();
a.cpp
void f(){/* implementation here */}
main.cpp
#include "a.h"
int main()
{
f();
}
Including "a.h" in main() is declaring the function. Once you compile the a.cpp once, you don't need it's source any more, the program will run provided you have at least access to the object file, but in order for the linker to find the function f() you need to declare it.
If one doesn’t specify the function prototype, the behavior is specific to C standard (either C90 or C99) that the compilers implement. Up to C90 standard, C compilers assumed the return type of the omitted function prototype as int. And this assumption at compiler side may lead to unspecified program behavior.
Later C99 standard specified that compilers can no longer assume return type as int. Therefore, C99 became more restrict in type checking of function prototype. But to make C99 standard backward compatible, in practice, compilers throw the warning saying that the return type is assumed as int. But they go ahead with compilation. Thus, it becomes the responsibility of programmers to make sure that the assumed function prototype and the actual function type matches.
To avoid all this implementation specifics of C standards, it is best to have function prototype.

how to use c and c++ together

There is a example I find:
in main.c
int main() {
cppsayhello("Hello from C to C++");
return 0;
}
in cppsayhello.cpp
#include<iostream>
#include"cppsayhello.h"
extern "C" void cppsayhello(char* str);
void cppsayhello(char *str) {
std::cout << str << std::endl;
}
It works! main.c includes nothing so how can main.c know of the existence of the function cppsayhello? Would somebody tell me how it works behind the scenes.
(I'm now working on an embeded system. The bottom-level is written in C, and I want to use c++ to construct top-level application. But It's hard to work with 2 language.)
The main.c is compiled by a C compiler that allows implicit function declaration. When C compiler finds a function that is not declare yet it assumes it is int function() which means function with any number of any parameters in C.
C99 and newer does not allow implicit declaration and the code would not compile with C99 compliant compiler.
It is a sign that your C compiler predates the 1999 standard, since later C compilers will reject that main() function.
Generally speaking, with older C compilers, your C code will link even when the usage of an implicitly declared function does not match the actual definition. The result is undefined behaviour (although, in practice, the code often still works - one possible manifestation of undefined behaviour is that the code works as expected with at least some compilers).
It works behind the scenes because C - unlike C++ - does not support function overloading. So any function named cppsayhello() will be given the same name (in the object file) by the compiler, so the linker can match things up. So you could define your cppsayhello() to have any return type, and any set of arguments, you desire - your code will still compile and link. However, the linker must only see one definition (it will complain about a multiply defined symbol if it encounters more than one definition of anything - for example, linking two object files that each contain a definition of some function).
Your code would avoid the undefined behaviour if the main() function had visibility of a proper declaration of the function.
void cppsayhello(const char *);
int main()
{
cppsayhello("Hello from C to C++");
return 0;
}
That will prevent the main() function compiling if it uses the function in any manner inconsistent with the declaration.
The whole thing is undefined behavior and works by luck.
A few things happen behind the scenes but your compiler should complain a lot.
in your main.c: in C a function the compiler does not know is implicitly expected to be of return type int without checking the parameters. (this applies to C older than C99. C99 or later will give you an error with this code)
in your cppsayhello.cpp: thanks to the extern "C" your C++ compiler creates an object file that contains a function with C calling conventions, without name mangeling.
the linker took both objects and finds in cppsayhello.obj a exportet symbol cppsayhello and in main.c a required symbol cppsayhello. so it links the two.
obviously they have different signatures but in your case the returned value is ignored and the parameters are compatible. But the actual runtime behavior may depend on architecture and compiler.
In Short: Your example is very bad code.

C++ Primer Questions

I am currently going through the 5th edition of C++ Primer by Lahoie, Lippman and Moo and have been struggling with a few things.
Firstly, I just wanted to confirm, when using any of the cctype functions, I have to make sure I include the header, right? Because, initially, I forgot to include it and yet it still ran. That's really confused me.
Also, I was browsing for a different problem (which I'll get to) and found another issue haha! When using anything from cctype, are I supposed to write it as std::/write using std::, e.g. if I use the tolower either write std::tolower at every instance/write a using statement for it. This would make sense as it did say that they are "defined in the std namespace" but I didn't realise and have been writing it without and haven't had an issue. And I'm guessing similar for size_t, right?
Speaking of size_t, I have an issue. This is my code:
// Exercise Section 3.5.2., Exercise 3.30
#include <iostream>
#include <cstddef>
using std::cout; using std::endl;
int main()
{
constexpr size_t num_size = 10;
int num[num_size] = {};
for (size_t n = 0; n < num_size; ++n) {
num[n] = n;
cout << num[n] << endl;
}
return 0;
}
So the code is supposed define an array of 10 ints and give each element the same value as its position in the array.
It runs correctly, but I am receiving an error at the num[n]=n part. It says Implicit conversion loses integer precision: size_t (aka 'unsigned long') to int.
I understand what this means, but my issue is that the book says "when we use a variable to subscript an array, we normally should define that variable to type size_t". I have done this and it gives this error. It does run fine but it seems like that sort of thing that can lead to errors.
P.S. In this code, like I asked above, should I have using std::size_t?
Must I include the header even though it works without?
Yes, you must always include at least one header providing each definition / declaration you need, unless the exact prototype / type definition is guaranteed and you put it directly into your source code.
Some standard headers may include others, which might let you get away with being sloppy some of the time, but you will rue it the day you upgrade / port to a different implementation.
I read all the declarations and definitions are "defined in the std namespace" but I didn't realise and have been writing it without and haven't had an issue. And I'm guessing similar for size_t, right?
Yes, it's the same. Due to compatibility, it is possible for the <c...> headers adopted by inclusion from C / Unicode to also provide their symbols in the global namespace.
17.6.1.2 Headers [headers]
1 Each element of the C++ standard library is declared or defined (as appropriate) in a header.175
2 The C++ standard library provides 55 C++ library headers, as shown in Table 14.
3 The facilities of the C standard Library are provided in 26 additional headers, as shown in Table 15.
4 Except as noted in Clauses 18 through 30 and Annex D, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in the C standard library (1.2) or the C Unicode TR, as appropriate, as if by inclusion. In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3).
5 Names which are defined as macros in C shall be defined as macros in the C++ standard library, even if C grants license for implementation as functions. [ Note: The names defined as macros in C include the following: assert, offsetof, setjmp, va_arg, va_end, and va_start. —end note ]
6 Names that are defined as functions in C shall be defined as functions in the C++ standard library.176
7 Identifiers that are keywords or operators in C++ shall not be defined as macros in C++ standard library headers.177
8 D.5, C standard library headers, describes the effects of using the name.h (C header) form in a C++ program. 178
In my example program I used size_t for the array index. That works, though I get a warning. Should I have done so, and could it in general lead to errors?
Well, naturally the same about namespace std applies, as you guessed.
As to the rest, there's a wonderful phrase: "Good advice comes with a rationale".
The reason you should use std::size_t for indices is that this type a) signals to readers that it's a size or index and b) it is guaranteed to be big enough.
In your case, a lowly int, with its guaranteed minimum maximum of 215-1 would have been perfectly fine.
An alternative is just casting to the proper type on assignment.
You asked:
Firstly, I just wanted to confirm, when using any of the cctype functions, I have to make sure I include the header, right?
Yes, that is right. You might get some function declarations or other declarations indirectly but that is not portable code. You should understand where the standard says a declaration is available and include that header file before using a function, a type, etc.
You asked:
And I'm guessing similar for size_t, right?
Yes, you should use std::size_t.
There is an SO post related to the topic. Browse Difference between size_t and std::size_t.
You asked:
In this code, like I asked above, should I have using std::size_t?
In the loop, it's OK to use int too. The suggestion to use std::size_t for indexing an array is a good suggestion but is not inviolable.
If you choose to use size_t for n, it's OK to use static_cast to convert it to an int to get rid of the compiler warning/error.
num[n] = static_cast<int>(n);
You declare your array as
int num[num_size] = {};
This means it is an array of int that has 10 elements.
Then you say
for (size_t n = 0; n < num_size; ++n)
num[n] = n;
Note that n is of type size_t aka unsigned long. Therefore you are putting unsigned long values into your int array, so they are being implicitly converted to int values.
The standard headers put a bunch of stuff in the global namespace. Ideally they wouldn't, but they do. Usually that's because something is really a macro rather than a typedef or function.
You can sometimes get away without including headers because some other header that you have included includes the missing one.
I have to make sure I include the header, right? Because, initially, I
forgot to include it and yet it still ran.
Some standard headers can include other headers. However it is a good idea to include a header explicitly if some declarations from the header are used in the program. It may occur such a way that in other implementations of the included headers the required header will not be included and the compiler will issue an error.
. This would make sense as it did say that they are "defined in the
std namespace" but I didn't realise and have been writing it without
and haven't had an issue.
The C++ Standard allows compilers to place C standard functions in the global namespace. Though even in this case it is better to specify explicitly namespace std where the function will be declared in any case.
As for the last question then the elements of the array have type int while you assign to them values of type size_t The problem is that type int can not accomodate all values of type size_t and the compiler warns you about this. You could explicitly specify casting that to say the compiler that you know what you are doing.
num[n] = ( int )n;
or
num[n] = static_cast<int>( n );

C/C++ linkage convention

When calling C++ algorithms like copy_if, transform etc which take a unary or binary function as the last argument, can I pass a C library function like atoi or tolower.
For e.g. below calls work fine and give the correct output (tried in ideone)
1) transform (foo, foo+5, bar, atoi);
2) transform (foo, foo+5, bar, ptr_fun(atoi));
3) transform(s.begin(),s.end(),s.begin(), static_cast<int (*)(int)>(tolower));
Is this usage guaranteed to work with all C++ compilers ?
The book thinking in C++ mentions "This works with some compilers, but it is not required to." The reason mentioned is (as I understand it) transform is C++ function and expects its last argument to have same calling convention.
The book also suggests a solution for this problem which is to create a wrapper function like this in a separate cpp file and do not include iostreams header file.
// tolower_wrapper.cpp
string strTolower(string s) {
transform(s.begin(), s.end(), s.begin(), tolower);
return s;
}
This works fine, but I did not understand how this resolves the calling convention issue ?
transform is still a c++ function and tolower is still a C function in the strTolower, so how this different calling conventions are handled here.
The first thing to note, which is not actually part of your question but which might help explain for someone reading this, is that the algorithms can take either a function pointer or a function object as an argument.
A function pointer is just that - a pointer to a function which expects to take a specific set of parameters and return a specific type.
A function object is an instance of a class which has overridden operator().
When expanding the algorithm template, the compiler will be able to see which of the two cases applies and will generate appropriate calling code.
In the case of a C function being used as a binary function in an algorithm, it is a function pointer that you are supplying. You can call a C function from C++, as long as it is declared extern C { ... }.
Many compilers come with header files for the C library functions which include something like this:
#ifdef __cplusplus
extern "C" {
#endif
/* function declarations here */
#ifdef __cplusplus
}
#endif
so that if you include a C library header from a C++ program, the contained functions will all be magically available to you. That part, however, is not guaranteed by the standard, which is why your book states it may not work with all compilers.
Another wrinkle is that you are not allowed to cast function pointers to a type with a different language linkage, which in at least some of your examples you are doing, although some compilers do seem to allow that anyway - for example see this GCC Bug.
The other catch, which applies specifically to tolower for example, is that some of the names of C library functions are also names of functions or templates in the C++ std library. For example, the name tolower is also defined in <locale>. This specific case is discussed in this GCC bug report. The use of a wrapper, compiled in a separate compilation unit which does not include the conflicting declarations, would resolve this issue.

In C++, is it safe/portable to use static member function pointer for C API callbacks?

In C++, is it safe/portable to use static member function pointer for C API callbacks? Is the ABI of a static member function the same as a C function?
It is not safe per the C++ standard. As stated in this SO posting:
A C callback function implemented in C++ must be extern "C". It may seem to work as a static function in a class because class-static functions often use the same calling convention as a C function. However, doing that is a bug waiting to happen (see comments below), so please don't - go through an extern "C" wrapper instead.
And according to comments made by Martin York in that answer there are real-world problems trying to do so on some platforms.
Make your C ABI callbacks extern "C".
Edit: Adding some supporting quotes from the standard (emphasis mine):
3.5 "Program and linkage":
After all adjustments of types (during which typedefs (7.1.3) are replaced by their definitions), the types specified by all declarations referring to a given object or function shall be identical, except that declarations for an array object can specify array types that differ by the presence or absence of a major array bound (8.3.4). A violation of this rule on type identity does not require a diagnostic. [3.5/10]
[Note: linkage to non-C++ declarations can be achieved using a linkage-specification (7.5). ] [3.5/11]
And
7.5 "Linkage specifications":
... Two function types with different language linkages are distinct types even if they are otherwise identical. [7.5/1]
So if the code making the callback is using C language bindings for the callback, then the callback target (in the C++ program) must as well.
After searching and several breaks while attacking other problems, I found an answer which is clear and succinct (for standardese, anyway):
Calling a function through an expression whose function type has a language linkage that is different from the language linkage of the function type of the called function's definition is undefined. [5.2.2/1]
I still maintain that it is problematic at a fundamental level to use text from the C++ standard to define the behavior of a C library compiled with a C compiler, and exactly how that interlanguage interoperability works is very implementation-specific; however, this is the closest I think either standard can (currently) hope to define such interaction.
In particular, this is undefined behavior (and isn't using a C library so that issue doesn't arise):
void call(void (*pf)()) { pf(); } // pf() is the UB
extern "C" void f();
int main() { call(f); }
// though I'm unsure if a diagnostic is required for call(f)
Comeau does give a diagnostic at call(f) (though it can do that even if the diagnostic isn't required).
This isn't undefined behavior, and shows how to include language linkage in a function pointer type (which is through a typedef):
extern "C" typedef void F();
void call(F* pf) { pf(); }
extern "C" void f();
int main() { call(f); }
Or could be written:
extern "C" {
typedef void F();
void f();
}
void call(F* pf) { pf(); }
int main() { call(f); }
For all the Windows C++ compilers that I'm aware of, the answer is yes, but nothing in the language standard guarantees this. I wouldn't let that stop you however, it's a very common way of implementing callbacks using C++ - you may find you need to declare the static functions as WINAPI however. This is taken from an old threading library of my own:
class Thread {
...
static DWORD WINAPI ThreadFunction( void * args );
};
where this is the callback use by te Windows threading API.
ABI isn't covered by either the C or C++ standards, even though C++ does give you "language linkage" through extern "C". Therefore, ABI is fundamentally compiler/platform specific. Both standards leave many, many things up to the implementation, and this is one of them.
Consequently, writing 100% portable code—or switching compilers—is hard to impossible, but allows vendors and users considerable flexibility in their specific products. This flexibility allows more space and time efficient programs, in ways that don't have to be anticipated in advance by the standards committees.
As I understand it, ISO's rules do not allow a standard more often than once every 10 years (but there can be various publications, such as TC1 and TR1 for C++). Plus there is the idea (I'm not sure if this comes from ISO, is carried over from the C committee, or even from elsewhere) to "distill"/standardize existing practice rather than going off into left field, and there are many existing practices, some of which conflict.