您的位置:首页 > 其它

MFC的一些实用的基础知识

2013-09-29 00:00 232 查看


一、_T()函数

_T("")是一个宏,他的作用是让你的程序支持Unicode编码。因为Windows使用两种字符集ANSI和UNICODE,前者就是通常使用的单字节方式,但这种方式处理象中文这样的双字节字符不方便,容易出现半个汉字的情况。而后者是双字节方式,方便处理双字节字符。

Windows NT的所有与字符有关的函数都提供两种方式的版本,而Windows 9x只支持ANSI方式。如果你编译一个程序为ANSI方式,_T实际不起任何作用。而如果编译一个程序为UNICODE方式,则编译器会把"Hello"字符串以UNICODE方式保存。_T和_L的区别在于,_L不管你是以什么方式编译,一律以UNICODE方式保存。

LPSTR:32bit指针指向一个字符串,每个字符占1字节。
LPCSTR:32-bit指针指向一个常字符串,每个字符占1字节。
LPCTSTR:32-bit指针指向一个常字符串,每字符可能占1字节或2字节,取决于Unicode是否定义。
LPTSTR:32-bit指针每字符可能占1字节或2字节,取决于Unicode是否定义。

L是表示字符串资源为Unicode的。比如 wchar_t Str[] = L"Hello World!"; 这个就是双子节存储字符了。

_T是一个适配的宏。当 #ifdef _UNICODE 的时候 ,_T就是L。没有#ifdef _UNICODE的时候,_T就是ANSI的。

比如:

1
LPTSTR
lpStr
=
new
TCHAR
[32];
2
TCHAR
*
szBuf = _T(
"Hello"
);
以上两句使得无论是在UNICODE编译条件下都是正确编译的。而且MS推荐你使用相匹配的字符串函数。比如处理LPTSTR或者LPCTSTR 的时候,不要用strlen,而是要用_tcslen。否则在UNICODE的编译条件下,strlen不能处理 wchar_t*的字符串。

T是非常有意思的一个符号(TCHAR、LPCTSTR、LPTSTR、_T()、_TEXT()...),它表示使用一种中间类型,既不明确表示使用 MBCS,也不明确表示使用 UNICODE。那到底使用哪种字符集?编译的时候才决定。

将char字符串转换成Unicode字符串。 T是个宏,不是函数。在需要双字节的函数,或COM里需要双字节的串。为了国际兼容。其实很简单。Visual C++里边定义字符串的时候,用_T来保证兼容性,VC支持ascii和unicode两种字符类型,用_T可以保证从ascii编码类型转换到unicode编码类型的时候,程序不需要修改。

如果将来你不打算升级到unicode,那么也不需要_T,_t("hello world") 在ansi的环境下,它是ansi的,如果在unicode下,那么它将自动解释为双字节字符串,既unicode编码。这样做的好处,不管是ansi环境,还是unicode环境,都适用。

在vc++中的字符串_T("ABC")和一个普通的字符串“ABC”有什么区别?_T("ABC")表示如果定义了unicode,它表示 L"ABC",每个字符为16位,宽字符字符串。if not UNICODE,它就是ascii的"ABC",每个字符为8位。"ABC"就是指ascii字符串"ABC"。相当于:

1
#ifdef
_UNICODE
2
#define
_T("ABC") L"ABC"
3
#else
4
#define
_T("ABC") "ABC"
5
#endif
_T("ABC")中的一个字符和汉字一样,占两个字节,而在"ABC"中,英文字符占一个字节,汉字占两个字节。


二、堆和栈

1、“堆”和“栈”在C++中主要是指存放数据或者说是变量、对象的在内存中的区域,如同现实中美国和中国的区别,表面上是在内存中的位置不同,但是分配内存的方式却大不相同,如同美国和中国虽然表面上都是国家,但是社会制度、各种福利各种机构都不同,一句话就是内存中的不同区域。

2、C++中“堆”:在一个程序中堆是一片内存,不是有堆内存之说,一般都是程序员手动分配,在C++中则是一般用new操作符(如果不使用C的malloc系列,好像只能用new)分配的内存,同样也只能程序员手动释放,不然会有内存泄露。当然了给什么分配内存,那只能给变量、类对象分配,所以存放的也是类对象和变量。

3、C++中“栈”:是程序自动分配的内存,比如调用某个函数,传递参数时(值传递),那么这个参数的值是在“栈”内存上分配的,当这个函数退出后占用的“栈”内存也就自己释放了。


三、Windows Socket

Socket的实现方法:

Socket是连接应用程序与网络驱动程序的桥梁。它在应用程序中创建,通过绑定操作与驱动程序建立关系。此后,应用程序送给Socket数据,由Socket交给驱动程序,驱动程序再把数据向网络上发送出去。计算机从网络上收到与该Socket绑定的IP地址和端口号相关的数据后,由驱动程序交给Socket,应用程序便可从该Socket中提取接收到的数据。网络应用程序就是这样运用Socket进行数据的发送与接收的。

ISO/OSI七层参考模型(ISO:国际标准化组织 OSI:Open System Interconnection):

物理层:提供二进制传输,确定在通信信道上如何传输比特流。
数据链路层:提供介质访问,加强物理层的传输功能,建立一条无差错的传输线路。
网络层:提供IP寻址和路由。因为在网络上数据可以经由多条线路到达目的地,网络层负责找出最佳的传输路线。
传输层:为源端主机到目的端主机提供可靠的数据传输服务,隔离网络的上下层协议,使得网络应用与下层协议无关。
会话层:在两个相互通信的应用进程之间建立、组织和协调其相互之间的通信。
表示层:处理被传送数据的表示问题,即信息的语法和语义。

对等层通信的实质:对等层实体之间虚拟通信。下层向上层提供服务,实际通信在最底层完成。

各层所使用的协议:

应用层:远程登录协议Telnet、文件传输协议FTP、超文本传输协议HTTP、域名服务DNS、简单邮件传输协议SMTP、邮局协议POP3。
传输层:传输控制协议TCP、用户数据报协议UDP。
网络层:网际协议IP、Internet互联网控制报文协议ICMP、Internet组管理协议IGMP。

TCP/IP模型:应用层、传输层、网络层、网络接口层。

TCP/IP模型与OSI模型对照如下:

应用层:应用层、表示层、会话层。
传输层:传输层。
网络层:网络层。
网络接口层:数据链路层、物理层。

端口:一种抽象的软件结构(包括一些数据结构和I/O缓冲区)。

套接字的类型:

流式套接字(SOCK_STREAM),基于TCP协议实现。
数据报套接字(SOCK_DGRAM),UDP协议实现。
原始套接字(SOCK_RAW)

Windows Socket “TCP”网络编程实例,一些开发步骤如下。

“TCP”服务器端:

加载套接字库。
创建套接字。
绑定地址信息。
绑定套接字。
监听套接字。
“Accept”等待用户请求。
“send”发送数据。
"recv"接收数据。
关闭“使用中的套接字”,继续循环等待。

“TCP”客户端:

加载套接字库。
创建套接字。
绑定地址信息。
绑定套接字。
发出请求。
接收数据。
发送数据。
关闭套接字。
“WSACleanup”终止“套接字库”的使用。(服务器端一直循环运行,所有没有)。

对于UDP通信,不需要建立连接,直接进行收/发就可以了。


四、多线程

1、程序和进程

程序是计算机指令的集合,它以文件的形式存储在磁盘上。而进程是正在运行的程序的实例。比如,我们编译生成的“exe”文件是一个可执行程序,存储在磁盘上就是程序。点击运行后,就启动了该程序的一个实例,我们称之为进程。一个程序可以有多个进程,也就是一个程序可以产生多个实例。

2、进程和线程

进程从来不执行任何东西,它是线程的容器,真正完成代码执行的是线程。单个进程可能包含若干个线程,但至少包含一个主线程。

3、进程的地址空间

系统赋予每个进程独立的虚拟地址空间。对于32位操作系统,运行32位的进程,这个地址空间是4G。因为对于32位指针来说,它的寻址的范围是2的32次方,即4G。这就是为什么32位操作系统,内存条一般不超过4G的原因。

4、虚拟内存。

在磁盘上有一个“pagefile.sys”文件,它是页文件,页文件透明的为应用程序增加了内存,这一部分就是虚拟内存。

5、线程。

线程的内核对象:操作系统用来存放线程统计信息的小型的数据结构。
线程栈:它用于维护线程在执行代码是所需要的所有函数参数和局部变量。

同一个进程的不同线程运行在同一个进程环境下,它们共享资源,所以可以非常容易的实现相互之间的通信。线程运行在操作系统为其分配的CPU时间片上,对于单核CPU,就要多个线程来回切换。多核CPU就可以实现多个线程的并发执行。采用多线程而不是多进程,是因为线程只有一个内核对象和一个栈,占用内存少。而对于进程每一个都要分配4GB的虚拟地址空间,占用资源多。而且进程切换需要交换整个地址空间。线程之间的切换只是执行环境的改变。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: