为何要将整型变量强制转化为指针

为何要将整型变量强制转化为指针
这个标题包含二层含义:

1、整型变量能强制转化为指针吗?例如下面的形式:
DWORD  ia=10;
LPVOID  lp = (LPVOID) ia;

我们在程序中测试一下吧

#include <iostream>
#include <atlbase.h>
using namespace std;
void main()
{
 DWORD ia =10;//定义了一个整形变量
 LPVOID lp =(LPVOID)ia;//强制转化成指针
 cout << lp << endl;//看看lp是什么
 cout << (DWORD)lp << endl;//再把指针强制转化为整形,看看是什么
 system("pause");
 return;
}
输出结果:
0000000A
10
!原来把整形变量强制转化为指针,也就是把十进制的整型表达形式换成了十六进制的指针表达形式
Ia=10 是十进制方式, 0000000A是32位的十六进制指针表达形式,都是10,换汤不换药。
还可以把LPVOID指针强制转化为DWORD整型,也就是把十六进制转化为十进制

第一眼看到这种表达方式,感到很别扭,不规范,正正规规的应该如下面这样
DWORD ia =10;
LPVOID lp = (LPVOID) &ia;
这样看着很顺畅,很好,取ia 变量的地址,转化为LPVOID指针,在这里是指针转成指针。是很正规的表达方式。如下:

#include <iostream>
#include <atlbase.h>
using namespace std;
void main()
{
 DWORD ia =10;//定义了一个整形变量
 LPVOID lp =(LPVOID) &ia;//取ia地址,然后转为指针
 cout << lp << endl;//看看lp是什么
 //cout << *lp << endl;//错误,不能直接从LPVOID指针类型中取值
 //cout << (DWORD)(*lp)<< endl;
 cout << *(DWORD*)lp << endl;
 //要从LPVOID指针中取值,要先把LPVOID指针转成别的类型的指针,然后再取值
 system("pause");
 return;
}
看着很顺的代码,指针转指针类型,比把整型突然转成指针舒服,要注意的是LPVOID是一个万能指针能型,可以顺利的和其它指针类型互相转换。

2、那为什么要把整型变量很突兀的转成指针,而不采用第二种先取地址,再转成指针的形式呢?

原因是这样的:很多API函数都有LPVOID参数,当我们在一个函数中以局部变量设置LPVOID参数时,我们就不能取局部变量的地址传给API函数的LPVOID参数,因为一出函数体,这个局部变量作用域失效,传给API函数的参数就是不可知状态。因此,在局部函数里,不能给API函数直接传地址。如果实在要传地址参数,则一般是申请一块动态存储区,把首地址传给API参数。如果局部变量是整形,呵呵,我们可以用上面的简便方法,把整形按值传给参数,类型不对,则强制把整形转换成指针,按赋值拷备方式传给LPVOID参数,即可。请看下面例子:
这是一个线程局部存储的简单例子,看其中整形转指针的应用
#include <stdio.h>
#include <windows.h>
#include <process.h>

// 利用TLS记录线程的运行时间

DWORD g_tlsUsedTime;
void InitStartTime();
DWORD GetUsedTime();


UINT __stdcall ThreadFunc(LPVOID)
{
 int i;

 // 初始化开始时间
 InitStartTime();

 // 模拟长时间工作
 i = 10000*10000;
 while(i--) { }

 // 打印出本线程运行的时间
 printf(" This thread is coming to end. Thread ID: %-5d, Used Time: %d ", 
      ::GetCurrentThreadId(), GetUsedTime());
 return 0;
}

int main(int argc, char* argv[])
{
 UINT uId;
 int i;
 HANDLE h[10];

 // 通过在进程位数组中申请一个索引,初始化线程运行时间记录系统
 g_tlsUsedTime = ::TlsAlloc();

 // 令十个线程同时运行,并等待它们各自的输出结果
 for(i=0; i<10; i++)
 {
  h[i] = (HANDLE)::_beginthreadex(NULL, 0, ThreadFunc, NULL, 0, &uId);
 }
 for(i=0; i<10; i++)
 {
  ::WaitForSingleObject(h[i], INFINITE);
  ::CloseHandle(h[i]);
 }

 // 通过释放线程局部存储索引,释放时间记录系统占用的资源
 ::TlsFree(g_tlsUsedTime);
 return 0;
}

// 初始化线程的开始时间
void InitStartTime()
{
 // 获得当前时间,将线程的创建时间与线程对象相关联
 DWORD dwStart = ::GetTickCount();
 ::TlsSetValue(g_tlsUsedTime, (LPVOID)dwStart);//这里不能传&dwstart,因为是局部变量,所以//按值传,再强转为指针,虽然是指针形式,其实保存的是一个十六位进制的数
}

// 取得一个线程已经运行的时间
DWORD GetUsedTime()
{
 // 获得当前时间,返回当前时间和线程创建时间的差值
 DWORD dwElapsed = ::GetTickCount();
 dwElapsed = dwElapsed - (DWORD)::TlsGetValue(g_tlsUsedTime);
//这里的TlsGetValue()返回的是一个指针,这里再强转为DWORD型,前后匹配,很好很强大
 return dwElapsed;
}

原文地址:https://www.cnblogs.com/youxin/p/3349365.html