Skip to content

Commit ce019b2

Browse files
authored
Merge pull request MicrosoftDocs#732 from mikeblome/mb-linkage
Updates to linkage content
2 parents 992a13a + a73b448 commit ce019b2

12 files changed

Lines changed: 514 additions & 489 deletions

‎.openpublishing.redirection.json‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,36 @@
210210
"redirect_url": "/cpp/cpp/cpp-language-reference",
211211
"redirect_document_id": false
212212
},
213+
{
214+
"source_path": "docs/cpp/types-of-linkage.md",
215+
"redirect_url": "/cpp/cpp/program-and-linkage-cpp",
216+
"redirect_document_id": false
217+
},
218+
{
219+
"source_path": "docs/cpp/linkage-in-names-with-file-scope.md",
220+
"redirect_url": "/cpp/cpp/program-and-linkage-cpp",
221+
"redirect_document_id": false
222+
},
223+
{
224+
"source_path": "docs/cpp/linkage-in-names-with-class-scope.md",
225+
"redirect_url": "/cpp/cpp/program-and-linkage-cpp",
226+
"redirect_document_id": false
227+
},
228+
{
229+
"source_path": "docs/cpp/linkage-in-names-with-block-scope.md",
230+
"redirect_url": "/cpp/cpp/program-and-linkage-cpp",
231+
"redirect_document_id": false
232+
},
233+
{
234+
"source_path": "docs/cpp/names-with-no-linkage.md",
235+
"redirect_url": "/cpp/cpp/program-and-linkage-cpp",
236+
"redirect_document_id": false
237+
},
238+
{
239+
"source_path": "docs/cpp/using-extern-to-specify-linkage.md",
240+
"redirect_url": "/cpp/cpp/extern-cpp",
241+
"redirect_document_id": false
242+
},
213243
{
214244
"source_path": "docs/cpp/support-for-cpp11-14-17-features-modern-cpp.md",
215245
"redirect_url": "/cpp/visual-cpp-language-conformance",

‎docs/cpp/TOC.md‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
### [Declarations and Definitions](declarations-and-definitions-cpp.md)
3636
#### [Overview of Declarators](overview-of-declarators.md)
3737
#### [Specifiers](specifiers.md)
38+
#### [extern](extern-cpp.md)
39+
#### [Header files](header-files-cpp.md)
3840
#### [Point of declaration in C++](point-of-declaration-in-cpp.md)
3941
#### [Initializers](initializers.md)
4042
#### [Aliases and typedefs](aliases-and-typedefs-cpp.md)
@@ -48,13 +50,9 @@
4850
#### [decltype](decltype-cpp.md)
4951
#### [Attributes](attributes.md)
5052
### [Scope (Visual C++)](scope-visual-cpp.md)
53+
### [Header Files](header-files-cpp.md)
5154
### [Program and Linkage](program-and-linkage-cpp.md)
52-
#### [Types of Linkage](types-of-linkage.md)
53-
#### [Linkage in Names with File Scope](linkage-in-names-with-file-scope.md)
54-
#### [Linkage in Names with Class Scope](linkage-in-names-with-class-scope.md)
55-
#### [Linkage in Names with Block Scope](linkage-in-names-with-block-scope.md)
56-
#### [Names with No Linkage](names-with-no-linkage.md)
57-
#### [Using extern to Specify Linkage](using-extern-to-specify-linkage.md)
55+
#### [extern](using-extern-to-specify-linkage.md)
5856
### [Startup and Termination](startup-and-termination-cpp.md)
5957
#### [main: Program Startup](main-program-startup.md)
6058
##### [Using wmain Instead of main](using-wmain-instead-of-main.md)

‎docs/cpp/extern-cpp.md‎

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
title: "extern (C++) | Microsoft Docs"
3+
ms.custom: ""
4+
ms.date: "04/12/2018"
5+
ms.reviewer: ""
6+
ms.suite: ""
7+
ms.technology: ["cpp-language"]
8+
ms.tgt_pltfrm: ""
9+
ms.topic: "language-reference"
10+
f1_keywords: ["extern", "extern_CPP"]
11+
dev_langs: ["C++"]
12+
helpviewer_keywords: ["extern keyword [C++], linkage to non-C++ functions", "declarations, external", "external linkage, extern modifier"]
13+
ms.assetid: 1e2f0ae3-ae98-4410-85b5-222d6abc865a
14+
caps.latest.revision: 11
15+
author: "mikeblome"
16+
ms.author: "mblome"
17+
manager: "ghogen"
18+
ms.workload: ["cplusplus"]
19+
---
20+
# extern (C++)
21+
22+
The **extern** keyword is applied to a global variable, function or template declaration to specify that the name of that thing has *external linkage*. For background information on linkage and why the use of global variables is discouraged, see [Program and linkage](program-and-linkage-cpp.md).
23+
24+
The **extern** keyword has four meanings depending on the context:
25+
26+
1. in a non-const global variable declaration, **extern** specifies that the variable or function is defined in another translation unit. The **extern** must be applied in all files except the one where the variable is defined.
27+
1. in a const variable declaration, it specifies that the variable has external linkage. The **extern** must be applied to all declarations in all files. (Global const variables have internal linkage by default.)
28+
1. **extern "C"** specifies that the function is defined elsewhere and uses the C-language calling convention. The extern "C" modifier may also be applied to multiple function declarations in a block.
29+
1. in a template declaration, it specifies that the template has already been instantiated elsewhere. This is an optimization that tells the compiler that it can re-use the other instantiation rather than creating a new one at the current location. For more information about this use of **extern**, see [Templates](templates-cpp.md).
30+
31+
## extern linkage for non-const globals
32+
33+
When the linker sees **extern** before a global variable declaration, it looks for the definition in another translation unit. Declarations of non-const variables at global scope are external by default; only apply **extern** to the declarations that don't provide the definition.
34+
35+
```cpp
36+
//fileA.cpp
37+
int i = 42; // declaration and definition
38+
39+
//fileB.cpp
40+
extern int i; // declaration only. same as i in FileA
41+
42+
//fileC.cpp
43+
extern int i; // declaration only. same as i in FileA
44+
45+
//fileD.cpp
46+
int i = 43; // LNK2005! 'i' already has a definition.
47+
extern int i = 43; // same error (extern is ignored on definitions)
48+
```
49+
50+
## extern linkage for const globals
51+
52+
A **const** global variable has internal linkage by default. If you want the variable to have external linkage, apply the **extern** keyword to definition as well as to all other declarations in other files:
53+
54+
```cpp
55+
//fileA.cpp
56+
extern const int i = 42; // extern const definition
57+
58+
//fileB.cpp
59+
extern const int i; // declaration only. same as i in FileA
60+
```
61+
62+
## extern constexpr linkage
63+
64+
In Visual Studio 2017 version 15.3 and earlier, the compiler always gave a constexpr variable internal linkage even when the variable was marked extern. In Visual Studio 2017 version 15.5, a new compiler switch ([/Zc:externConstexpr](../build/reference/zc-externconstexpr.md)) enables correct standards-conforming behavior. Eventually this will become the default.
65+
66+
```cpp
67+
extern constexpr int x = 10; //error LNK2005: "int const x" already defined
68+
```
69+
70+
If a header file contains a variable declared extern constexpr, it needs to be marked **__declspec(selectany)** in order to correctly have its duplicate declarations combined:
71+
72+
```cpp
73+
extern constexpr __declspec(selectany) int x = 10;
74+
```
75+
76+
## extern "C" and extern "C++" function declarations
77+
78+
In C++, when used with a string, **extern** specifies that the linkage conventions of another language are being used for the declarator(s). C functions and data can be accessed only if they are previously declared as having C linkage. However, they must be defined in a separately compiled translation unit.
79+
80+
Microsoft C++ supports the strings **"C"** and **"C++"** in the *string-literal* field. All of the standard include files use the **extern** "C" syntax to allow the run-time library functions to be used in C++ programs.
81+
82+
## Example
83+
84+
The following example shows how to declare names that have C linkage:
85+
86+
```cpp
87+
// Declare printf with C linkage.
88+
extern "C" int printf(const char *fmt, ...);
89+
90+
// Cause everything in the specified
91+
// header files to have C linkage.
92+
extern "C" {
93+
// add your #include statements here
94+
#include <stdio.h>
95+
}
96+
97+
// Declare the two functions ShowChar
98+
// and GetChar with C linkage.
99+
extern "C" {
100+
char ShowChar(char ch);
101+
char GetChar(void);
102+
}
103+
104+
// Define the two functions
105+
// ShowChar and GetChar with C linkage.
106+
extern "C" char ShowChar(char ch) {
107+
putchar(ch);
108+
return ch;
109+
}
110+
111+
extern "C" char GetChar(void) {
112+
char ch;
113+
ch = getchar();
114+
return ch;
115+
}
116+
117+
// Declare a global variable, errno, with C linkage.
118+
extern "C" int errno;
119+
```
120+
121+
If a function has more than one linkage specification, they must agree; it is an error to declare functions as having both C and C++ linkage. Furthermore, if two declarations for a function occur in a program — one with a linkage specification and one without — the declaration with the linkage specification must be first. Any redundant declarations of functions that already have linkage specification are given the linkage specified in the first declaration. For example:
122+
123+
```cpp
124+
extern "C" int CFunc1();
125+
...
126+
int CFunc1(); // Redeclaration is benign; C linkage is
127+
// retained.
128+
129+
int CFunc2();
130+
...
131+
extern "C" int CFunc2(); // Error: not the first declaration of
132+
// CFunc2; cannot contain linkage
133+
// specifier.
134+
```
135+
136+
## See Also
137+
138+
- [Keywords](../cpp/keywords-cpp.md)
139+
- [Program and linkage](program-and-linkage-cpp.md)
140+
- [extern Storage-Class Specifier in C](../c-language/extern-storage-class-specifier.md)
141+
- [Behavior of Identifiers in C](../c-language/behavior-of-identifiers.md)
142+
- [Linkage in C](../c-language/linkage.md)

‎docs/cpp/header-files-cpp.md‎

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
---
2+
title: "Header files (C++) | Microsoft Docs"
3+
ms.custom: ""
4+
ms.date: "04/20/2018"
5+
ms.reviewer: ""
6+
ms.suite: ""
7+
ms.technology: ["cpp-language"]
8+
ms.tgt_pltfrm: ""
9+
ms.topic: "language-reference"
10+
dev_langs: ["C++"]
11+
helpviewer_keywords: ["header files [C++]"]
12+
author: "mikeblome"
13+
ms.author: "mblome"
14+
manager: "ghogen"
15+
ms.workload: ["cplusplus"]
16+
---
17+
# Header files (C++)
18+
19+
The names of program elements such as variables, functions, classes, and so on must be declared before they can be used. For example, you can't just write `x = 42` without first declaring 'x'.
20+
21+
```cpp
22+
int x; // declaration
23+
x = 42; // use x
24+
```
25+
26+
The declaration tells the compiler whether is an **int**, a **double**, a **function**, a **class** or some other thing. Furthermore, each name must be declared (directly or indirectly) in every .cpp file in which it is used. When you compile a program, each .cpp file is compiled independently into a compilation unit. The compiler has no knowledge of what names are declared in other compilation units. That means that if you define a class or function or global variable, you must provide a declaration of that thing in each additional .cpp file that uses it. Each declaration of that thing must be exactly identical in all files. A slight inconsistency will cause errors, or unintended behavior, when the linker attempts to merge all the compilation units into a single program.
27+
28+
To minimize the potential for errors, C++ has adopted the convention of using *header files* to contain declarations. You make the declarations in a header file, then use the #include directive in every .cpp file or other header file requires that declaration. The #include directive inserts a copy of the header file directly into the .cpp file prior to compilation.
29+
30+
## Example
31+
32+
The following example shows a common way to declare a class and then use it in a different source file. We'll start with the header file, **my_class.h**. It contains a class definition, but note that the definition is incomplete; the member function `do_something` is not defined:
33+
34+
```cpp
35+
// my_class.h
36+
namespace N
37+
{
38+
class my_class
39+
{
40+
public:
41+
void do_something();
42+
};
43+
44+
}
45+
```
46+
47+
Next, create an implementation file (typically with a .cpp or similar extension). We'll call the file my_class.cpp and provide a definition for the member declaration. We add an `#include` directive for "my_class.h" file in order to have the my_class declaration inserted at this point in the .cpp file, and we include **\<iostream>** to pull in the declaration for `std::cout`. Note that quotes are used for header files in the same directory as the source file, and angle brackets are used for standard library headers. Also, many standard library headers do not have .h or any other file extension.
48+
49+
In the implementation file, we can optionally use a **using** statement to avoid having to qualify every mention of "my_class" or "cout" with "N::" or "std::". Don't put **using** statements in your header files!
50+
51+
```cpp
52+
// my_class.cpp
53+
#include "my_class.h" // header in local directory
54+
#include <iostream> // header in standard library
55+
56+
using namespace N;
57+
using namespace std;
58+
59+
void my_class::do_something()
60+
{
61+
cout << "Doing something!" << endl;
62+
}
63+
```
64+
65+
Now we can use `my_class` in another .cpp file. We #include the header file so that the compiler pulls in the declaration. All the compiler needs to know is that my_class is a class that has a public member function called `do_something()`.
66+
67+
```cpp
68+
// my_program.cpp
69+
#include "my_class.h"
70+
71+
using namespace N;
72+
73+
int main()
74+
{
75+
my_class mc;
76+
mc.do_something();
77+
return 0;
78+
}
79+
```
80+
81+
After the compiler finishes compiling each .cpp file into .obj files, it passes the .obj files to the linker. When the linker merges the object files it finds exactly one definition for my_class; it is in the .obj file produced for my_class.cpp, and the build succeeds.
82+
83+
## Include guards
84+
85+
Typically, header files have an *include guard* or a **#pragma once** directive to ensure that they are not inserted multiple times into a single .cpp file.
86+
87+
// my_class.h
88+
#ifndef MY_CLASS_H // include guard
89+
#define MY_CLASS_H
90+
91+
92+
namespace N
93+
{
94+
class my_class
95+
{
96+
public:
97+
void do_something();
98+
};
99+
100+
}
101+
102+
#endif /* MY_CLASS_H */
103+
104+
## What to put in a header file
105+
106+
Because a header file might potentially be included by multiple files, it cannot contain definitions that might produce multiple definitions of the same name. The following are not allowed, or are considered very bad practice:
107+
108+
- built-in type definitions at namespace or global scope
109+
- non-inline function definitions
110+
- non-const variable definitions
111+
- aggregate definitions
112+
- unnamed namespaces
113+
- using directives
114+
115+
Use of the **using** directive will not necessarily cause an error, but can potentially cause a problem because it brings the namespace into scope in every .cpp file that directly or indirectly includes that header.
116+
117+
## Sample header file
118+
119+
The following example shows the various kinds of declarations and definitions that are allowed in a header file:
120+
121+
```cpp
122+
#pragma once
123+
#include <vector> // #include directive
124+
#include <string>
125+
126+
namespace N // namespace declaration
127+
{
128+
129+
inline namespace P
130+
{
131+
//...
132+
}
133+
134+
enum class colors : short { red, blue, purple, azure };
135+
136+
137+
const double PI = 3.14; // const and constexpr definitions
138+
constexpr int MeaningOfLife{ 42 };
139+
constexpr int get_meaning()
140+
{
141+
static_assert(MeaningOfLife == 42, "unexpected!"); // static_assert
142+
return MeaningOfLife;
143+
}
144+
using vstr = std::vector<int>; // type alias
145+
extern double d; // extern variable
146+
147+
#define LOG // macro definition
148+
149+
#ifdef LOG // conditional compilation directive
150+
void print_to_log();
151+
#endif
152+
153+
154+
class my_class // regular class definition,
155+
{ // but no non-inline function definitions
156+
157+
friend class other_class;
158+
public:
159+
void do_something(); // definition in my_class.cpp
160+
inline void put_value(int i) { vals.push_back(i); } // inline OK
161+
162+
private:
163+
vstr vals;
164+
int i;
165+
};
166+
167+
struct RGB
168+
{
169+
short r{ 0 }; // member initialization
170+
short g{ 0 };
171+
short b{ 0 };
172+
};
173+
174+
template <typename T> // template definition
175+
class value_store
176+
{
177+
public:
178+
value_store<T>() = default;
179+
void write_value(T val)
180+
{
181+
//... function definition OK in template
182+
}
183+
private:
184+
std::vector<T> vals;
185+
};
186+
187+
template <typename T> // template declaration
188+
class value_widget;
189+
190+
}

0 commit comments

Comments
 (0)