linux里tchar.h没有那个文件或目录怎么处

linux里tchar.h没有那个文件或目录怎么处,第1张

如果我没有记错的话,tchar.h应该是VS中的头文件,也就是Windows平台才有的头文件,在Linux上编译Windows代码才会提示“tchar.h:没有那个文件或目录”,因为在Linux上不管安装什么第三方函数库都不会有这个头文件的。你可以在网上下载这个头文件(网上有为Windows代码移植而自己编写的),然后放到你需要编译的源码目录中,但是你需要编译的代码也应该需要进行改写,因为Windows代码如果不在Linux上改写,虽然解决了tchar.h的错误信息,再来编译时还会报其他的错误信息的。

在<WCHAR.h>头文件中有定义

typedef unsigned short wchar_t

就是 wide character type 的意思

在 美国资讯交换标准码(ASCII: American Standard Code for Information Interchange)

开发过程中 为了节约成本(排除8位, 当时每位元的存储空间成本很昂贵) 最终由美国国家标准协会发布了7位版本的方案 记录在ANSI X3.4-1986 中

该标准在美国及拉丁字母国家使用方便 但在远东 西欧南部 会遇到拉丁字母中不存在的字母

比如俄语(斯拉夫) 希腊语 希伯来语 阿拉伯语 以及 汉字 日语 韩语

为了解决的字符集不同的恶心问题(内码转换) 诞生了Unicode字元集 它比ASCII多了一倍空间

这个wchar_t 就是Unicode对应的资料结构 它是16位的 可以装得下汉字哦

wchar_t *p = L"ooxx!"这个L告诉编译器, 把字母扩展为宽字元

你也会见到 _T(ooxx) 或者 TEXT(之类的写法) 他们都是为了让你的代码能在美欧以外运行

#ifdef UNICODE //UNICODE版

#define __T(x) L##x//这##字符串连接符 你应该知道滴

#else //ASCII版

#define __T(x) (x)

#endif

#define _T(x) __T(x)

#define _TEXT(x) __T(x)

因此他们都是一样的

在windows的编程中 更普遍的写法是用WCHAR取代wchar_t

因为符合微软的命名规则 当然你如果喜欢Linux的话...

typedef char CHAR

typedef wchar_t WCHAR

如果你的代码是国际版本(多语言版)

你也可以用TCHAR.. 它是一个依赖识别字的宏 可以是char 也可以是wchar_t...

C/C++函数参数的传递方式有三种:值传递(pass by value)、指针传递(pass bypointer)、引用传递(pass by reference)。

C/C++函数参数的传递通道是通过堆栈传递,默认遵循__cdecl(C声明方式),参数由调用者从右往左逐个压入堆栈,在函数调用完成之后再由调用者恢复堆栈。(Win32API遵循stdcall传参规范的,不在本文讨论范围)

下面是测试代码

void Swap(__int64* _pnX, __int64* _pnY)

{

__int64 nTemp = *_pnX

*_pnX = *_pnY

*_pnY = nTemp

}

void Swap(__int64&_nX, __int64&_nY)

{

__int64 nTemp = _nX

_nX = _nY

_nY = nTemp

}

void SetValue(__int64 _nX)

{

__int64 nTemp = _nX

}

// Test001

void GetMemory(__int64* _pBuff)

{

_pBuff = new __int64[4]

}

// Test002

void GetMemory(__int64** _ppBuff)

{

*_ppBuff = new __int64[4]

}

int _tmain(int argc, _TCHAR* argv[])

{

__int64 nA = 0x10

__int64 nB = 0x20

// Test to pass by pointer

Swap(&nA, &nB)

// Test to pass by reference

Swap(nA, nB)

// Test to pass by value

SetValue(nA)

// Test the pointer that points the pointer

__int64* _pArray = NULL

GetMemory(&_pArray)

delete[] _pArray

_pArray = NULL

// Test the pointer

GetMemory(_pArray)

return 0

}

指针传递和引用传递

// 下面看一下对应的反汇编的代码(VS版)

__int64 nA = 0x10

0041370E movdword ptr [nA],10h

movdword ptr [ebp-8],0

__int64 nB = 0x20

0041371C movdword ptr [nB],20h

movdword ptr [ebp-18h],0

// Test to pass by pointer

Swap(&nA, &nB)

0041372A leaeax,[nB]

0041372D pusheax

0041372E leaecx,[nA]

pushecx

callSwap (4111E5h)

addesp,8

// Test to pass by reference

Swap(nA, nB)

0041373A leaeax,[nB]

0041373D pusheax

0041373E leaecx,[nA]

pushecx

callSwap (4111E0h)

addesp,8

// GCC版

0x00401582 <+30>:leaeax,[esp+0x18]

0x00401586 <+34>:movDWORD PTR [esp+0x4],eax

0x0040158a <+38>:leaeax,[esp+0x1c]

0x0040158e <+42>:movDWORD PTR [esp],eax

0x00401591 <+45>:call 0x401520 <Swap(int*, int*)>

0x00401596 <+50>:leaeax,[esp+0x18]

0x0040159a <+54>:movDWORD PTR [esp+0x4],eax

0x0040159e <+58>:leaeax,[esp+0x1c]

0x004015a2 <+62>:movDWORD PTR [esp],eax

0x004015a5 <+65>:call 0x401542 <Swap(int&, int&)>

通过上面的反汇编代码,我们可以看出指针传递和引用传递在机制是一样的,都是将指针值(即地址)压入栈中,调用函数,然后恢复栈。Swap(nA, nB)和Swap(&nA, &nB)在实际上的汇编代码也基本上一模一样,都是从栈中取出地址来。由此可以看出引用和指针在效率上是一样的。这也是为什么指针和引用都可以达到多态的效果。指针传递和引用传递其实都是改变的地址指向的内存上的值来达到修改参数的效果。

值传递

下面是值传递对应的反汇编代码

// Test to pass by value

SetValue(nA)

0041374A moveax,dword ptr [ebp-8]

0041374D pusheax

0041374E movecx,dword ptr [nA]

00413751 pushecx

00413752 callSetValue (4111EAh)

00413757 addesp,8

因为我的机器是32位的CPU,从上面的汇编代码可以看64Bit的变量被分成2个32Bit的参数压入栈中。这也是我们常说的,值传递会形成一个拷贝。如果是一个自定义的结构类型,并且有很多参数,那么如果用值传递,这个结构体将被分割为非常多个32Bit的逐个拷贝到栈中去,这样的参数传递效率是非常慢的。所以结构体等自定义类型,都使用引用传递,如果不希望别人修改结构体变量,可以加上const修饰,如(const MY_STRUCT& _value)

下面来看一下Test001函数对应的反汇编代码的参数传递

__int64* _pArray = NULL

004137E0 movdword ptr [_pArray],0

// Test the pointer

GetMemory(_pArray)

moveax,dword ptr [_pArray]

pusheax

callGetMemory (411203h)

0041381B addesp,4

从上面的汇编代码可以看出,其实是0被压入到栈中作为参数,所以GetMemory(_pArray)无论做什么事,其实都与指针变量_pArray无关。GetMemory()分配的空间是让栈中的临时变量指向的,当函数退出时,栈得到恢复,结果申请的空间没有人管,就产生内存泄露的问题了。《C++ Primer》将参数传递分为引用传递和非引用传递两种,非引用传递其实可以理解为值传递。这样看来,指针传递在某种意义上也是值传递,因为传递的是指针的值(1个4BYTE的值)。值传递都不会改变传入实参的值的。而且普通的指针传递其实是改变的指针变量指向的内容。

下面再看一下Test002函数对应的反汇编代码的参数传递

__int64* _pArray = NULL

004137E0 movdword ptr [_pArray],0

GetMemory(&_pArray)

004137E7 leaeax,[_pArray]

004137EA pusheax

004137EB callGetMemory (4111FEh)

004137F0 addesp,4

从上面的汇编代码lea eax,[_pArray] 可以看出,_pArray的地址被压入到栈中去了。

然后看一看GetMemory(&_pArray)的实现汇编代码。

0x0040159b <+0>:push ebp

0x0040159c <+1>:movebp,esp

0x0040159e <+3>:subesp,0x18

0x004015a1 <+6>:movDWORD PTR [esp],0x20

0x004015a8 <+13>:call 0x473ef0 <_Znaj>

0x004015ad <+18>:movedx,DWORD PTR [ebp+0x8]

0x004015b0 <+21>:movDWORD PTR [edx],eax

0x004015b2 <+23>:leave

0x004015b3 <+24>:ret

蓝色的代码是分配临时变量空间,然后调用分配空间函数分配空间,得到的空间指针即eax.

然后红色的汇编代码即从ebp+0x8的栈上取到上面压入栈中的参数_pArray的地址.

mov DWORD PTR [edx],eax即相当于把分配的空间指针eax让edx指向,也即让_pArray指向分配的空间eax.

总之,无论是哪种参数传递方式,参数都是通过栈上的临时变量来间接参与到被调用函数的。指针作为参数,其本身的值是不可能被改变的,能够改变的是其指向的内容。引用是通过指针来实现的,所以引用和指针在效率上一样的。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7258630.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-03
下一篇 2023-04-03

发表评论

登录后才能评论

评论列表(0条)

保存