18.7. Inherently Nonportable Features
One of the hallmarks of the C programming language is the ability to write low-level programs that can be readily moved from one machine to another. The process of moving a program to a new machine is referred to as "porting," so C programs are said to be portable.To support low-level programming, C defines some features that are inherently nonportable. The fact that the size of the arithmetic types vary across machines Section 2.1, p. 34) is one such nonportable feature that we have already encountered. In this section we'll cover two additional nonportable features that C++ inherits from C: bit-fields and the volatile qualifier. These features make it easier to interface directly to hardware.C++ adds another nonportable feature to those that it inherits from C: linkage directives, which make it possible to link to programs written in other languages.
18.7.1. Bit-fields
A special class data member, referred to as a bit-field, can be declared to hold a specified number of bits. Bit-fields are normally used when a program needs to pass binary data to another program or hardware device.

The mode bit-field has two bits, modified only one, and the other members each have three bits. Bit-fields defined in consecutive order within the class body are, if possible, packed within adjacent bits of the same integer, thereby providing for storage compaction. For example, in the preceding declaration, the five bit-fields will be stored in the single unsigned int first associated with the bit-field mode. Whether and how the bits are packed into the integer is machine-dependent.
typedef unsigned int Bit;
class File {
Bit mode: 2;
Bit modified: 1;
Bit prot_owner: 3;
Bit prot_group: 3;
Bit prot_world: 3;
// ...
};

Using Bit-fields
A bit-field is accessed in much the same manner as the other data members of a class. For example, a bit-field that is a private member of its class can be accessed only from within the definitions of the member functions and friends of its class:
Section 5.3, p. 154):
void File::write()
{
modified = 1;
// ...
}
void File::close()
{
if (modified)
// ... save contents
}
Classes that define bit-field members also usually define a set of inline member functions to test and set the value of the bit-field. For example, the class File might define the members isRead and isWrite:
enum { READ = 01, WRITE = 02 }; // File modes
int main() {
File myFile;
myFile.mode |= READ; // set the READ bit
if (myFile.mode & READ) // if the READ bit is on
cout << "myFile.mode READ is set\n";
}
With these member functions, the bit-fields can now be declared as private members of class File.The address-of operator (&) cannot be applied to a bit-field, so there can be no pointers referring to class bit-fields. Nor can a bit-field be a static member of its class.
inline int File::isRead() { return mode & READ; }
inline int File::isWrite() { return mode & WRITE; }
if (myFile.isRead()) /* ... */
18.7.2. volatile Qualifier
volatile when its value might be changed in ways outside either the control or detection of the compiler. The volatile keyword is a directive to the compiler that it should not perform optimizations on such objects.The volatile qualifier is used in much the same way as is the const qualifier. It is an additional modifier to a type:
display_register is a volatile object of type int. curr_task is a pointer to a volatile Task object. ixa is a volatile array of integers. Each element of the array is considered to be volatile. bitmap_buf is a volatile Screen object. Each of its data members is considered to be volatile.In the same way that a class may define const member functions, it can also define member functions as volatile. Only volatile member functions may be called on volatile objects.Section 4.2.5 (p. 126) described the interactions between the const qualifier and pointers. The same interactions exist between the volatile qualifier and pointers. We can declare pointers that are volatile, pointers to volatile objects, and pointers that are volatile that point to volatile objects:
volatile int display_register;
volatile Task *curr_task;
volatile int ixa[max_size];
volatile Screen bitmap_buf;
As with const, we may assign the address of a volatile object (or copy a pointer to a volatile type) only to a pointer to volatile. We may use a volatile object to initialize a reference only if the reference is volatile.
volatile int v; // v is a volatile int
int *volatile vip; // vip is a volatile pointer to int
volatile int *ivp; // ivp is a pointer to volatile int
// vivp is a volatile pointer to volatile int
volatile int *volatile vivp;
int *ip = &v; // error: must use pointer to volatile
*ivp = &v; // ok: ivp is pointer to volatile
vivp = &v; // ok: vivp is volatile pointer to volatile
Synthesized Copy Control Does Not Apply to Volatile Objects
One important difference between the treatment of const and volatile is that the synthesized copy and assignment operators cannot be used to initialize or assign from a volatile object. The synthesized copy-control members take parameters that are const references to the class type. However, a volatile object cannot be passed to a plain or const reference.If a class wants to allow volatile objects to be copied or to allow assignment from or to a volatile operand, it must define its own versions of the copy constructor and/or assignment operator:
By defining the parameter to the copy-control members as a const volatile reference, we can copy or assign from any kind of Foo: a plain Foo, a const Foo, a volatile Foo, or a const volatile Foo.
class Foo {
public:
Foo(const volatile Foo&); // copy from a volatile object
// assign from a volatile object to a non volatile objet
Foo& operator=(volatile const Foo&);
// assign from a volatile object to a volatile object
Foo& operator=(volatile const Foo&) volatile;
// remainder of class Foo
};

18.7.3. Linkage Directives: extern "C"
C++ programs sometimes need to call functions written in another programming language. Most often, that other language is C. Like any name, the name of a function written in another language must be declared. That declaration must specify the return type and parameter list. The compiler checks calls to external-language functions in the same way that it handles ordinary C++ functions. However, the compiler typically must generate different code to call functions written in other languages. C++ uses linkage directives to indicate the language used for any non-C++ function.
Declaring a Non-C++ Function
A linkage directive can have one of two forms: single or compound. Linkage directives may not appear inside a class or function definition. The linkage directive must appear on the first declaration of a function.As an example, let's look at some of the C functions declared in the cstdlib header. Declarations in that header might look something like
The first form consists of the extern keyword followed by a string literal, followed by an "ordinary" function declaration. The string literal indicates the language in which the function is written.We can give the same linkage to several functions at once by enclosing their declarations inside curly braces following the linkage directive. These braces serve to group the declarations to which the linkage directive applies. The braces are otherwise ignored, and the names of functions declared within the braces are visible as if the functions were declared outside the braces.
// illustrative linkage directives that might appear in the C++ header <cstring>
// single statement linkage directive
extern "C" size_t strlen(const char *);
// compound statement linkage directive
extern "C" {
int strcmp(const char*, const char*);
char *strcat(char*, const char*);
}
Linkage Directives and Header Files
The multiple-declaration form can be applied to an entire header file. For example, the C++ cstring header might look like
When a #include directive is enclosed in the braces of a compound linkage directive, all ordinary function declarations in the header file are assumed to be functions written in the language of the linkage directive. Linkage directives can be nested, so if the header contained a function with a linkage directive the linkage of that function is unaffected.
// compound statement linkage directive
extern "C" {
#include <string.h> // C functions that manipulate C-style strings
}

Exporting Our C++ Functions to Other Langauges
By using the linkage directive on a function definition, we can make a C++ function available to a program written in another language:
When the compiler generates code for this function, it will generate code appropriate to the indicated language.
// the calc function can be called from C programs
extern "C" double calc(double dparm) { /* ... */ }

Languages Supported by Linkage Directives
A compiler is required to support linkage directives for C. A compiler may provide linkage specifications for other languages. For example, extern "Ada", extern "FORTRAN", and so on.

Preprocessor Support for Linking to C
It can be useful sometimes to compile the same source file in both C or C++. The preprocessor name __cplusplus (two underscores) is automatically defined when compiling C++, so we can conditionally include code based on whether we are compiling C++.
#ifdef __cplusplus
// ok: we're compiling C++
extern "C"
#endif
int strcmp(const char*, const char*);
Overloaded Functions and Linkage Directives
The interaction between linkage directives and function overloading depends on the target language. If the language supports overloaded functions, then it is likely that a compiler that implements linkage directives for that language would also support overloading of these functions from C++.The only language guaranteed to be supported by C++ is C. The C language does not support function overloading, so it should not be a surprise that a linkage directive can be specified only for one C function in a set of overloaded functions. It is an error to declare more than one function with C linakage with a given name:
In C++ programs, it is fairly common to overload C functions. However, the other functions in the overload set must all be C++ functions:
// error: two extern "C" functions in set of overloaded functions
extern "C" void print(const char*);
extern "C" void print(int);
The C version of calc can be called from C programs and from C++ programs. The additional functions are C++ functions with class parameters that can be called only from C++ programs. The order of the declarations is not significant.
class SmallInt { /* ... */ };
class BigNum { /* ... */ };
// the C function can be called from C and C++ programs
// the C++ functions overload that function and are callable from C++
extern "C" double calc(double);
extern SmallInt calc(const SmallInt&);
extern BigNum calc(const BigNum&);
Pointers to extern "C" Functions
The language in which a function is written is part of its type. To declare a pointer to a function written in another programming language, we must use a linkage directive:
When pf is used to call a function, the function call is compiled assuming that the call is to a C function.
// pf points to a C function returning void taking an int
extern "C" void (*pf)(int);

void (*pf1)(int); // points to a C++ function
extern "C" void (*pf2)(int); // points to a C function
pf1 = pf2; // error: pf1 and pf2 have different types

Linkage Directives Apply to the Entire Declaration
When we use a linkage directive, it applies to the function and any function point-ers used as the return type or as a parameter type:
This declaration says that f1 is a C function that doesn't return a value. It has one parameter, which is a pointer to a function that returns nothing and takes a single int parameter. The linkage directive applies to the function pointer as well as to f1. When we call f1, we must pass it the name of a C function or a pointer to a C function.Because a linkage directive applies to all the functions in a declaration, we must use a typedef to pass a pointer to a C function to a C++ function:
// f1 is a C function; its parameter is a pointer to a C function
extern "C" void f1(void(*)(int));
// FC is a pointer to C function
extern "C" typedef void FC(int);
// f2 is a C++ function with a parameter that is a pointer to a C function
void f2(FC *);
Exercises Section 18.7.3
Exercise 18.34:Explain these declarations and indicate whether they are legal:
extern "C" int compute(int *, int);
extern "C" double compute(double *, double);