1. 程式人生 > >《Beginning C++17》-學習筆記-Chapter 10-Program Files and Preprocessing Directives

《Beginning C++17》-學習筆記-Chapter 10-Program Files and Preprocessing Directives

#include "..\Power.h"
/*including the file called Power.h located in the folder that includes the foler that includes this file.*/

Each source file, along with the contents of all the header files that you include in it, is called a translation unit.

The compiler processes each translation unit in a program independently to generate an object file.The object file contains machine code and information about references to entities such as functions that were not defined in the translation unit—external entities in other words.The set of object files for a complete program is processed by the linker, which establishes all necessary connections between the object files to produce the executable program module.

The combined process of compiling and linking translation units is referred to as translation.

In a given translation unit, no variable, function, class type, enumeration type, or template must ever be defined more than once.You can have more than one declaration for a variable or function, for example, but there must never be more than one definition that determines what it is and causes it to be created.

A declaration introduces a name into a scope.A definition not only introduces the name but also defines what it is.In other words, all definitions are declarations, but not all declarations are definitions.

The way that names in a translation unit are handled in the compile / link process is determined by a property that a name can have called linkage.Linkage expresses where in the program code the entity that is represented by a name can be.Every name that you use in a program either has linkage or doesn’t.A name has linkage when you can use it to access something in your program that is outside the scope in which the name is declared.If this isn’t the case, it has no linkage.If a name has linkage, then it can have internal linkage or external linkage.Therefore, every name in a translation unit has internal linkage, external linkage, or no linkage.

Internal linkage : The entity that the name represents can be accessed from anywhere within the same translation unit.For example, the names of non - inline variables defined at global scope that are specified as const have internal linkage by default.

External linkage : A name with external linkage can be accessed from another translation unit in addition to the one in which it is defined.In other words, the entity that the name represents can be shared and accessed throughout the entire program.All the functions that we have written so far have external linkage and so do both non - const and inline variables defined at global scope.

No linkage : When a name has no linkage, the entity it refers to can be accessed only from within the scope that applies to the name.All names that are defined within a block—local names, in other words—have no linkage.

In a program made up of several files, the linker establishes(or resolves) the connection between a function call in one source file and the function definition in another.When the compiler compiles a call to the function, it only needs the information contained in a function prototype to create the call.This prototype is contained within each declaration of the function.The compiler doesn’t mind whether the function’s definition occurs in the same file or elsewhere.This is because function names have external linkage by default.If a function is not defined within the translation unit in which it is called, the compiler flags the call as external and leaves it for the linker to sort out.

You can’t specify an initial value in an extern declaration because it’s a declaration of the name, not a definition of a variable.Declaring a variable as extern implies that it is defined in another translation unit.

/*A const variable, however, has internal linkage by default, which makes it unavailable in other translation units.You can override this by using the extern keyword in the definition :*/

extern const int power_range{ 3 }; // Definition of a global constant with external linkage

In the old days, the way to mark a name (function or variable name) for internal linkage was by adding the static keyword. The recommended way to define names with internal linkage today is through unnamed namespaces.
 

#define IDENTIFIER_FOR_A_SENTENCE "This is a sentence defined by an identifier."

#include <iostream>
#include <iomanip>

int main()
{
	std::cout << IDENTIFIER_FOR_A_SENTENCE << std::endl;
}
#define MAX(A, B) ((A) >= (B) ? (A) : (B))
#include <iostream>
#include <iomanip>

int main()
{
	std::cout << MAX(11, 22) << std::endl;//output 22
}
// Working with preprocessor operators
#include <iostream>
#define DEFINE_PRINT_FUNCTION(NAME, COUNT, VALUE) \
void NAME##COUNT() { std::cout << #VALUE << std::endl; }

DEFINE_PRINT_FUNCTION(fun, 123, Test 1 "2" 3)
/*With the definition, the line DEFINE_PRINT_FUNCTION(fun, 123, Test 1 "2" 3) became:
void fun123() { std::cout << "Test 1 \"2\" 3" << std::endl; }
*/

int main()
{
	fun123();
}

Standard Library names are declared within the std namespace.

#include <iostream>
#include <iomanip>

int main()
{
	std::cout << ::pow(2.0, 3) << std::endl;
	/*To explicitly access names defined in the global namespace, you use the scope resolution operator
without a left operand, for example, ::power(2.0, 3). This is only really required, though, if there is a more
local declaration with the same name that hides that global name.*/

}

All the Standard Library headers have preprocessing directives to prevent duplication.

All names declared inside an unnamed namespace have internal linkage(even names defined with an extern specifier).If a function is not supposed to be accessible from outside a particular translation unit, you should always define it in an unnamed namespace.Using a static specifier for this purpose is no longer recommended.
 

//  use the date and time macros to record when your program was last compiled.
#include <iostream>

int main()
{
	std::cout << "Program last compiled at " << __TIME__ << " on " << __DATE__ << std::endl;
}

// Demonstrating assertions
#include <iostream>

#include <cassert>
#define NDEBUG
int main()
{
	int y{ 5 };

	for (int x{}; x < 20; ++x)
	{
		std::cout << "x = " << x << " y = " << y << std::endl;
		assert(x < y);
		/*You should see an assertion message in the output when the value of x reaches 5. The program is
terminated by the assert() macro by calling std::abort() when x < y evaluates to false. The abort()
function is from the Standard Library, and its effect is to terminate the program immediately. As you can see
from the output, this happens when x reaches the value 5. The macro displays the output on the standard
error stream, cerr, which is always the command line. The message contains the condition that failed and
also the file name and line number in which the failure occurred.*/
	}
}