原文链接:http://blog.csdn.net/candyliuxj/article/details/7853938
(1)编译单元(模块)
在VC或VS上编写完代码,点击编译按钮准备生成exe文件时,编译器做了两步工作:
第一步:将每个.cpp和相应的.h文件编译成obj文件;
第二步:将工程所有的obj文件进行Link,生成最终的.exe文件。
这样,错误可能在两个地方产生:
一个是在编译的时候发生的错误,主要是语法错误;
一个是在链接的时候的错误,主要是重复定义变量等。
编译单元指在编译阶段生成的每个obj文件。
一个obj文件就是一个编译单元。
一个.cpp和它对应的.h文件共同组成了一个编译单元。
一个工程由很多编译单元组成,每个obj文件里包含了变量存储的相对地址等。
(2)变量的声明与定义
函数或变量在声明时,并没有给它实际的物理内存空间,它有时候可保证你的程序编译通过;函数或变量在定义时,它就在内存中有了实际的物理空间。
如果你在编译单元中引用的外部变量没有在整个工程中任何一个地方定义的话,那么即使它在编译时可以通过,在链接时也会报错,因为程序在内存中找不到这个变量。
函数或变量可以声明多次,但定义只能一次。
(3)extern的作用
1 /**********res.h声明全局变量************/ 2 #pragma once 3 4 #include <QSemaphore> 5 6 const int g_nDataSize = 1000; // 生产者生产的总数据量 7 const int g_nBufferSize = 500; // 环形缓冲区的大小 8 9 extern char g_szBuffer[]; // 环形缓冲区 10 extern QSemaphore g_qsemFreeBytes; // 控制环形缓冲区的空闲区(指生产者还没填充数据的区域,或者消费者已经读取过的区域) 11 extern QSemaphore g_qsemUsedBytes; // 控制环形缓冲区中的使用区(指生产者已填充数据,但消费者没有读取的区域) 12 /**************************/
上述代码中g_nDataSize、g_nBufferSize为全局常量,其他为全局变量。
1 /**********res.cpp定义全局变量************/ 2 #pragma once 3 #include "res.h" 4 5 // 定义全局变量 6 char g_szBuffer[g_nBufferSize]; 7 QSemaphore g_qsemFreeBytes(g_nBufferSize); 8 QSemaphore g_qsemUsedBytes; 9 /**************************/
在其他编译单元中使用全局变量时只要包含其所在头文件即可。
1 /**********类ConsumerThread使用全局变量************/ 2 #include "consumerthread.h" 3 #include "res.h" 4 #include <QDebug> 5 6 ConsumerThread::ConsumerThread(QObject* parent) 7 : QThread(parent) { 8 9 } 10 11 ConsumerThread::ConsumerThread() { 12 13 } 14 15 ConsumerThread::~ConsumerThread() { 16 17 } 18 19 void ConsumerThread::run() { 20 for (int i = 0; i < g_nDataSize; i++) { 21 g_qsemUsedBytes.acquire(); 22 qDebug()<<"Consumer "<<g_szBuffer[i % g_nBufferSize]; 23 g_szBuffer[i % g_nBufferSize] = ' '; 24 g_qsemFreeBytes.release(); 25 26 } 27 qDebug()<<"&&Consumer Over"; 28 } 29 /**************************/
1 /***********res.h**********/ 2 static char g_szBuffer[6] = "12345"; 3 void fun(); 4 /************************/
1 /***********res.cpp**********/ 2 #include "res.h" 3 #include <iostream> 4 using namespace std; 5 6 void fun() { 7 for (int i = 0; i < 6; i++) { 8 g_szBuffer[i] = 'A' + i; 9 } 10 cout<<g_szBuffer<<endl; 11 } 12 /************************/
1 /***********test1.h**********/ 2 void fun1(); 3 /************************/
1 /***********test1.cpp**********/ 2 #include "test1.h" 3 #include "res.h" 4 #include <iostream> 5 using namespace std; 6 7 void fun1() { 8 fun(); 9 10 for (int i = 0; i < 6; i++) { 11 g_szBuffer[i] = 'a' + i; 12 } 13 cout<<g_szBuffer<<endl; 14 } 15 /************************/
1 /***********test2.h**********/ 2 void fun2(); 3 /************************/
1 /***********test2.cpp**********/ 2 #include "test2.h" 3 #include "res.h" 4 #include <iostream> 5 using namespace std; 6 7 void fun2() { 8 cout<<g_szBuffer<<endl; 9 } 10 /************************/
1 /***********main.cpp**********/ 2 #include "test1.h" 3 #include "test2.h" 4 5 int main() { 6 fun1(); 7 fun2(); 8 9 system("PAUSE"); 10 return 0; 11 } 12 /************************/
运行结果如下:
1 extern const char g_szBuffer[]; //写入 .h中 2 const char g_szBuffer[] = "123456"; // 写入.cpp中