C + + mixed with

Source: Internet
Author: User
Tags class definition define function joins mixed types of functions

In the C + + project source code, it is often inevitable to see the following:

1

2

3

4

5

6

7

8

9

#ifdef __cplusplus

extern "C" {

#endif

/*...*/

#ifdef __cplusplus

}

#endif

What's the use of it, you know. And this kind of question often appears in the interview or the written test. Below I will introduce it from the following aspects:

· 1, #ifdef_cplusplus/#endif _cplusplus and divergence

· 2, extern "C"

· 2.1, extern key word

· 2.2, "C"

· 2.3, summary of extern "C"

· 3, C and C + + call each other

· 3.1, C + + compilation and connection

· 3.2, c compilation and connection

· 3.3. C in C + + code call

· C + + code called in 3.4

· 4, C and C + + mixed call special function pointer

1, #ifdef_cplusplus/#endif _cplusplus and divergence

Before introducing the extern "C", let's look at the role of #ifdef _cplusplus/#endif _cplusplus. Obviously #ifdef/#endif, #ifndef/#endif用于条件编译, #ifdef_cplusplus/#endif _cplusplus--indicates that if a macro _cplusplus is defined, the #ifdef/# is executed The statement between the endif, otherwise it is not executed.

Why do you need #ifdef_cplusplus/#endif _cplusplus here? Because the C language does not support extern "C" declarations, if you understand the role of extern "C" is not necessary to do in C, this is the role of conditional compilation. A compile-time error occurs when an extern "C" is included in the. C file.

Now that I've talked about conditional compilation, I'll introduce an important application of it-- avoid repeating the header file . I remember the Tencent written test on this topic, give a similar code like the following (the following is my recent research on an open source Web server--mongoose header file mongoose.h a piece of code):

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#ifndef mongoose_header_included

#define Mongoose_header_included

#ifdef __cplusplus

extern "C" {

#endif/* __cplusplus * *

/*.................................

* Do something

*.................................

*/

#ifdef __cplusplus

}

#endif/* __cplusplus * *

#endif/* mongoose_header_included * *

Then I'll ask you to explain the macro #ifndef/#endif的作用 above. To explain a problem, let's look at two facts first:

· This header file mongoose.h may be included in the project by multiple source files (#include "mongoose.h"), and for a large project, these redundancies can cause errors because a header file contains a class definition or a inline function. Mongoose.h may be #include two times in a source file (for example, a.h header files contain mongoose.h and B.C #include and a.h in mongoose.h files)--This can be an error (in the same source file, a struct, Class etc. was defined two times).

· From the logical point of view and reduce the compile time, all require the removal of these redundancy. However, it is not only tedious and impractical for programmers to analyze and remove these redundancies, but the most important thing is that they sometimes need this redundancy to ensure that each module is independent .

To solve this problem, the code in the above

#ifndef mongoose_header_included
#define Mongoose_header_included
/*.................................*/
#endif/* mongoose_header_included * *

It worked. If mongoose_header_included is defined, #ifndef/#endif之间的内容就被忽略掉. As a result, the Mongoose.h header file is first seen at compile time and its contents are read and given a value of mongoose_header_included. When you see the mongoose.h header file again, the mongoose_header_included is defined and the mongoose.h content is not read again.

2, extern "C"

First the literal analysis of extern "C", which consists of two parts--extern keyword, "C". Here I will explain the meaning of extern "C" from these two aspects.

2.1, extern key word

In a project, you must ensure that functions, variables, enumerations, etc. are consistent in all source files, unless you specify the definition as partial. First comes an example:

?

1

2

3

4

5

6

7

FILE1.C:

int x=1;

int F () {do something here}

FILE2.C:

extern int x;

int f ();

void G () {x=f ();}

In file2.c, The X and F () used by g () are defined in file1.c. The extern keyword indicates that x in file2.c is simply a declaration of a variable that is not defining the variable x and allocating no memory space for X. Variable x can only be defined once as a global variable in all modules, otherwise a connection error will occur. However, it can be declared multiple times and the declaration must guarantee a consistent type, such as:

?

1

2

3

4

5

6

7

8

9

FILE1.C:

int x=1;

int b=1;

extern C;

FILE2.C:

int x;//x equals to default of int type 0

int f ();

extern double b;

extern int C;

There are three errors in this code:

1. x has been defined twice

2. b two times are declared as different types

3. C has been declared two times, but it is not defined

Back to the extern keyword, extern is a keyword that indicates the scope (visibility) of functions and Global variables in the C + + language, which tells the compiler that its declared functions and variables can be used in this module or in other modules. Typically, the module's header file provides the keyword extern declaration for functions and global variables that are referenced by this module to other modules. For example, if module B wants to refer to the global variables and functions defined in module A, just include the header file for module A. In this way, when a function in module A is called in Module B, module B cannot find the function in the compile phase, but it does not complain; it will find this function in the connection phase from the object code generated by module a compilation.

The keyword that corresponds to extern is static, and global variables and functions that are decorated with it can only be used in this module. Therefore, a function or variable can only be used by this module, it cannot be decorated by extern "C".

2.2, "C"

Typically, a C + + program contains part of the code written in other languages. Similarly, code snippets written in C + + may be used in code written in other languages. Code written in different languages is difficult to invoke, even the same code that is written but different compiler compiled code. For example, different implementations of different languages and the same language might not be the same in registering variables that keep parameters and parameters on the stack.

In order for them to conform to the uniform rules, you can specify a compilation and connection specification using extern. For example, declare C and C + + standard library functions STRCYP (), and specify that it should be linked according to C's compilation and connection protocol:

?

1

extern "C" char* strcpy (Char*,const char*);

Note that it differs from the following statement:

?

1

extern char* strcpy (Char*,const char*);

The following declaration only indicates that strcpy () is invoked at the time of the connection.

The extern "C" directive is useful because of the relative relationship between C and C + +. Note: The C in the extern "C" instruction represents a compilation and connection protocol, not a language. C means any language that conforms to the C language compilation and connection protocol, such as FORTRAN, assembler, etc.

It is also stated that the extern "C" instruction specifies only compilation and connection protocols, but does not affect semantics. For example, in a function declaration, extern "C" is specified, and still adheres to C + + type detection, parameter conversion rules.

Looking at one of the following examples, in order to declare a variable instead of defining a variable, you must specify the extern keyword when you declare it, but when you add "C", it does not change the semantics, but it changes the way it compiles and joins.

If you have many languages to add extern "C", you can put them in the extern "C" {}.

2.3, summary of extern "C"

Through the analysis of the above two sections, we know that the real purpose of extern "C" is to implement mixed programming of Class C and C + + . Preceding the statement in the C + + source file with an extern "C" indicates that it compiles and joins according to the compilation and connection specification of class C, rather than the compiled connection specification for C + +. This allows you to call a C + + function or variable in code in Class C. (Note: The Class C I am talking about here represents all languages consistent with the C language's compilation and connection)

3, C and C + + call each other

We know that extern "C" is the implementation of the Class C and C + + mixed programming. Below we will explain how to invoke C in C + + code, c C + + code. The first thing to understand is that C and C + + call each other, you need to know how they compile and connect, and how to use extern "C" to invoke each other.

3.1, C + + compilation and connection

C + + is an object-oriented language (although not a purely object-oriented language), it supports the overloading of functions, overloading This feature has brought us great convenience. To support this feature of function overloading, the C + + compiler actually takes the following overloaded functions:

?

1

2

3

4

void print (int i);

void print (char c);

void print (float f);

void print (char* s);

Compile as:

?

1

2

3

4

_print_int

_print_char

_print_float

_pirnt_string

Such a function name to uniquely identify each function. Note: Different compiler implementations may not be the same, but they all take advantage of this mechanism. So when the connection is calling print (3), it looks for functions such as _print_int (3). The following is a digression, precisely because of this, overload is considered not polymorphic, polymorphic is run-time dynamic binding ("a variety of Interface implementations"), if the hard to think that the overload is polymorphic, it is at most compile-time "polymorphism."

C + + variables, compilation is similar, such as global variables may compile g_xx, class variables compiled to C_xx, and so on. The connection is also followed by this mechanism to find the corresponding variable.

3.2, c compilation and connection

C language does not have overloads and classes of these features, it is not like C + + as print (int i), will be compiled into _print_int, but directly compiled to _print and so on. Therefore, if a function called C directly in C + + fails, because the connection calls print (3) in C, it will look for _print_int (3). Therefore, the role of extern "C" is reflected.

3.3. C in C + + code call

Suppose a C header file CHeader.h contains a function print (int i), and in order to be able to invoke it in C + +, you must add an extern keyword (the reason is described in the extern keyword section). Its code is as follows:

?

1

2

3

4

5

6

#ifndef C_header

#define C_header

extern void print (int i);

#endif C_header

The corresponding implementation file for the CHEADER.C code is:

?

1

2

3

4

5

6

#include <stdio.h>

#include "CHeader.h"

void print (int i)

{

printf ("Cheader%d\n", i);

}

The print (int i) function in C is now referenced in C + + code file C++.cpp:

?

1

2

3

4

5

6

7

8

9

extern "C" {

#include "CHeader.h"

}

int main (int argc,char** argv)

{

Print (3);

return 0;

}

Execute program output:

C + + code called in 3.4

Now replace the code that calls C + + in C, which is different from the code that calls it within C + +. The following code is defined in the CppHeader.h header file as follows:

?

1

2

3

4

5

6

#ifndef Cpp_header

#define Cpp_header

extern "C" void print (int i);

#endif Cpp_header

The corresponding implementation file CppHeader.cpp file in the following code:

?

1

2

3

4

5

6

7

8

#include "CppHeader.h"

#include <iostream>

using namespace Std;

void print (int i)

{

cout<< "Cppheader" <<i<<endl;

}

Call the print function in the code file C.C of C:

?

1

2

3

4

5

6

extern void print (int i);

int main (int argc,char** argv)

{

Print (3);

return 0;

}

Note that the "CppHeader.h" header file is #include directly in C's code file, and there is a compilation error. And if you do not add extern intprint (int i), there will be an error.

4, C and C + + mixed call special function pointer

When we mix C and C + +, we sometimes define function pointers in one language, while in the application we point the function pointer to another language-defined function. This is possible if C and C + + share the same compilation and connection, function invocation mechanisms. However, such a common mechanism is usually otherwise assumed to exist, so we have to be careful to ensure that the function is invoked in the desired manner.

And when specifying the compilation and concatenation of a function pointer, all types of functions, including function names, and variables introduced by functions, are compiled and connected in the way specified. The following example:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21st

22

23

24

25

26

27

28

typedef int (*FT) (const void*, const void*);//style of C + +

extern "C" {

typedef int (*CFT) (const void*,const void*);//style of C

void Qsort (void* p,size_t n,size_t sz,cft cmp);//style of C

}

void Isort (void* p,size_t n,size_t sz,ft cmp);//style of C + +

void Xsort (void* p,size_t n,size_t sz,cft cmp);//style of C

Style of C

extern "C" void Ysort (void* p,size_t n,size_t sz,ft cmp);

int compare (const void*,const void*);//style of C + +

extern "C" ccomp (const void*,const void*);//style of C

void f (char* v,int sz)

{

Error,as Qsort is style of C

But compare is style of C + +

Qsort (V,sz,1,&compare);

Qsort (V,sz,1,&ccomp);//ok

Isort (v,sz,1,&compare);//ok

Error,as Isort is style of C + +

But Ccomp is style of C

Isort (V,SZ,1,&CCOPM);

}

Note: the typedef int (*ft) (const void*, constvoid*), which represents an alias that defines a function pointer, has the feature that the function pointer points to functions that have a return value of int and two parameters. The parameter type can be a pointer of any type (because it is void*).

An example of the alias of the most typical function pointer is the signal of the signal processing function, which is defined as follows:

?

1

2

typedef void (*handler) (int);

HANDLER signal (int, HANDLER);

The code above defines the letter-handling function signal, which has a return value type of HANDLER, with two arguments int, HANDLER, respectively. This eliminates the need to define signal functions like this:

?

1

void (*signal (int, void (*) (int))) (int)

The benefits of the TypeDef can be clearly realized after comparison.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.