c++ c语言 - 控件及概述补充
C语言 基础概述2 - 控件及概述补充
dll 依赖库
一、dll概念
DLL:Dynamic Link Library,即动态链接库,这种库包含了可由多个程序同时使用的代码和数据。
它是microsoft在windows操作系统中实现共享函数库概念的一种实现方式。其中windows中 一些作为DLL实现的文件有:
-
ActiveX控件(.ocx)文件:如windows上的日历控件。 -
控制面板(.cpl)文件:控制面板中的每一项都是一个专用的DLL。 -
设备驱动程序(.drv)文件:如控制打印到打印机的打印机驱动程序。
DLL最初用于节约应用程序所需要的磁盘和内存空间。早前,在传统的非共享库中,一部分代码简单地附加到调用的程序中。如果两个程序同时调用同一个子程序,就会出现两份那段代码。相反,许多应用共享的代码能够切分到一个DLL中,在硬盘上存为一个文档,在内存中只需使用一个实例。
二、dll 优缺点
优点:
(1)节省内存和代码重用:当多个程序使用同一个函数库时,DLL可以减少在磁盘和物理内存中加载代码的重复量,且有助于代码的重用。
(2)模块化:DLL有助于促进模块式程序开发。模块化允许仅仅更改几个应用程序共享使用的一个DLL中的代码和数据而不需要更改应用程序自身。这种模块话的基本形式允许如Microsoft Office、Microsoft Visual Studio、甚至windows自身这样大的应用程序 使用较为紧凑的补丁和服务包。
缺点:
DLL Hell:即DLL地狱,指几个应用程序在使用同一个共享的DLL库时发生版本冲突。究其原因是因为共用。因为DLL Hell正是由于动态链接库可与其他程序共用函数、资源所导致。
三、dll与lib的关系
lib是静态链接库;DLL是动态链接库,一个编译时提供;一个运行时提供。
静态lib:它将导出声明(后面会讲)和实现均放到lib中,编译后所有代码都嵌入到宿主程序中去。
动态lib:相当于一个h文件,它是对实现部分(.DLL)的导出部分的声明。编译后只是将导出声明部分编译到宿主程序中,运行时需要相应的DLL文件的支持,否则无法工作。当生成一个新的DLL时,也会有配套的lib产生(即二者需一起分发),此时的lib即为动态lib(后面会有还有实验)。
四、如何生成一个DLL
在VS2012开发环境下,打开File\New\Project选项,可以选择Win32 Dynamic-Link Library或MFC AppWizard【dll】来以不同的方式创建Non-MFC DLL、Regular DLL、Extension DLL等不同种类的动态链接库。下面以选择Win32 Dynamic-Link Library方式来创建一个DLL(实现加法运算)。
// mydll.h file
extern "C" _declspec(dllexport) int add(int a, int b);
//mydll.cpp file
#include "mydll.h"
int add(int a, int b) //该DLL需要导出的函数功能:加法
{
return a + b;
}(1)前面的 extern “C” 告诉编译器函数可以在本模块或其他模块中使用,其中“C”表明需按照C语言方式编译和连接它,因为C++编译时,会对函数名进行修饰,用于实现函数重载,而C里面没有这个功能,所以需要用extern "C"在头文件进行声明的时候加以区分,以便链接时能进行正确地函数名查找。
(2)_declspec(dllexport)为导出函数关键字,意为需从DLL中导出该函数,以便使用。
(3) 之后会有一个dll文件生成以供使用。
五、如何调用一个DLL
下面实现两种调用方式:单独.dll 和.h + .lib + .dll结合
注:需把对应的 .dll 文件以及.lib 文件和.h文件(结合方式时)拷贝至调用的程序目录下
1)单纯使用.dll
#include<wtypes.h>
#include <winbase.h>
#include <iostream>
_declspec(dllimport) int Add(int a, int b); //导入声明,亦可以不加,如果加上可加快程序运行
typedef int(*pAdd)(int a,int b);
int main()
{
HINSTANCE hDLL;
pAdd Add;
hDLL=LoadLibrary(L"mydll.dll"); //加载 DLL文件
if(hDLL == NULL)std::cout<<"Error!!!\n";
Add=(pAdd)GetProcAddress(hDLL,"add"); //取DLL中的函数地址,以备调用
int a =Add(5,8);
std::cout<<"a: "<<a<<std::endl;
FreeLibrary(hDLL);
return 0;
}
2).h + .lib + .dll 结合方式
#include<wtypes.h>
#include <winbase.h>
#include <iostream>#include "../MyDll/mydll.h"
#pragma comment(lib,"mydll.lib") //将mydll.lib库文件连接到目标文件中(即本工程)
extern "C"_declspec(dllimport) int add(int a,int b);
int main()
{
int a =add(5,8);
std::cout<<"a: "<<a<<std::endl;
return 0;
}
CPU内部结构与寄存器
64位和32位系统的区别
-
寄存器是CPU内部最基本的 存储单元。 -
CPU对外是通过总线(地址、控制、数据)来和外部设备交互的,总线的宽度,是8位,同时CPU的寄存器也是8位,那么这个CPU就叫8位CPU. -
如果总线是32位,寄存器也是32位的,那么这个CPU就是32位CPU。 -
有一种CPU内部的寄存器是32位的,但总线是16位,准32为CPU. -
所有的64位CPU兼容32位的指令,32 位要兼容16位的指令,所以在64位的CPU.上是可以识别32位的指令。 -
在64位的CPU构架上运行了64位的软件操作系统,那么这个系统是64位。 -
在64位的CPU构架上,运行了32 位的软件操作系统,那么这个系统就是32位。 -
64位的软件不能运行在32位的CPU之上。.
寄存器、缓存、内存关系
-
按与CPU远近来分,离得最近的是寄存器,然后缓存(CPU缓存),最后内存。 -
CPU计算时,先预先把要用的数据从硬盘读到内存,然后再把即将要用的数据读到寄存器。 -
于是CPU<--->寄存器<--->内存,这就是它们之间的信息交换。 -
那为什么有缓存呢?因为如果经常操作内存中的同一址地的数据,就会影响速度。于是就在寄存器与内存之间设置一个缓存。 -
因为从缓存提取的速度远高于内存。当然缓存的价格肯定远远高于内存,不然的话,机器里就没有内存的存在。 -
由此可以看出,从远近来看: CPU <---> 寄存器. <---> 缓存<--->内存。
C语言嵌套汇编代码
#include <stdio.h>
int main(){
// 定义变量abc
int a;int b;int c;
__asm{
mov a,3 //3的值放在a的内存位置
mov b,4 //4的值放在b的内存位置
mov eax,a //a的内存值放在eax寄存器上
add eax,b // eax和b相加,依然把结果放在eax上
mov c,eax // eax寄存器放c上面
}
printf("%d\n",c);
return 0
}
printf格式化输出
格式字符用以指定输出项的数据类型和输出格式。
d格式:用来输出十进制整数。有以下几种用法:
%d:按整型数据的实际长度输出。 %md:m为指定的输出字段的宽度。如果数据的位数小于m,则左端补以空格,若大于m,则按实际位数输出 o格式:以无符号八进制形式输出整数。对长整型可以用"%lo"格式输出。同样也可以指定字段宽度用“%mo”格式输出。
例:
printf("%d, %o", -1, -1);
运行结果:-1,177777
程序解析:-1在内存单元中(以补码形式存放)为(1111111111111111)2,转换为八进制数为(177777)8。
x格式:以无符号十六进制形式输出整数。对长整型可以用"%lx"格式输出。同样也可以指定字段宽度用"%mx"格式输出。
u格式:以无符号十进制形式输出整数。对长整型可以用"%lu"格式输出。同样也可以指定字段宽度用“%mu”格式输出。
c格式:输出一个字符。
s格式:用来输出一个串。有几中用法
%s:例如:printf("%s", "CHINA")输出"CHINA"字符串(不包括双引号) %ms:输出的字符串占m列,如果字符串本身长度大于m,则突破获m的限制,将字符串全部输出。若串长小于m,则左补空格。 %-ms:如果串长小于m,则在m列范围内,字符串向左靠,右补空格。 %m.ns:输出占m列,但只取字符串中左端n个字符。这n个字符输出在m列的右侧,左补空格。 %-m.ns:其中m、n含义同上,n个字符输出在m列范围的左侧,右补空格。如果n>m,则自动取n值,即保证n个字符正常输出。 f格式:用来输出实数(包括单、双精度),以小数形式输出。有以下几种用法:
%f:不指定宽度,整数部分全部输出并输出6位小数。 %m.nf:输出共占m列,其中有n位小数,若数值宽度小于m左端补空格。 %-m.nf:输出共占m列,其中有n位小数,若数值宽度小于m右端补空格。 e格式:以指数形式输出实数。可用以下形式:
%e:数字部分(又称尾数)输出6位小数,指数部分占5位或4位。 %m.ne和%-m.ne:m、n和”-”字符含义与前相同。此处n指数据的数字部分的小数位数,m表示整个输出数据所占的宽度。 g格式:自动选f格式或e格式中较短的一种输出,且不输出无意义的零。
%a 浮点数、十六进制数字和p-记数法(C99)
%A 浮点数、十六进制数字和p-记法(C99)
%c 一个字符(char)
%C 一个ISO宽字符
%d 有符号十进制整数(int)(%e浮点数、e-记数法
%E 浮点数、E-记数法
%f 单精度浮点数(默认float)、十进制记数法(%.nf 这里n表示精确到小数位后n位.十进制计数)
%g 根据数值不同自动选择%f或%e.
%G 根据数值不同自动选择%f或%e.
%i 有符号十进制数(与%d相同)
%o 无符号八进制整数
%p 指针
%s 对应字符串char*(%S 对应宽字符串WCAHR*(%u无符号十进制整数(unsigned int)
%x 使用十六进制数字0f的无符号十六进制整数
%X 使用十六进制数字0f的无符号十六进制整数
%% 打印一个百分号
往期回顾
04
| 4、 数组
01 | |
02 | |
03 |3、 数据类型 |
图 | 郭嘉
文 | 郭嘉
扫码关注桔梗与少年
新浪微博:桔梗与少年