zoukankan      html  css  js  c++  java
  • 为何要将整型变量强制转化为指针

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

    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;
    }

  • 相关阅读:
    Leetcode Valid Sudoku
    Leetcode Surrounded Regions
    LeetCode Sqrt
    LeetCode POW
    LeetCode Next Permutation
    ACK-Ackermann, 阿克曼函数
    再不懂时序就 OUT 啦!,DBengine 排名第一时序数据库,阿里云数据库 InfluxDB 正式商业化!
    阿里云提供全托管 ZooKeeper
    性能压测中的SLA,你知道吗?
    第一个入驻阿里云自营心选商城,如今它已经是营收过亿的SaaS独角兽
  • 原文地址:https://www.cnblogs.com/youxin/p/3349365.html
Copyright © 2011-2022 走看看