zoukankan      html  css  js  c++  java
  • C语言、指针(二)

    指针(二)

    • 类型转换
    • &符号的使用
    • “带*类型” 的特征探测:求值
    • 用指针操作数组

     一、类型转换

    a、普通类型之间的类型转换

      在C语言中,经常会使用到类型转换问题,举个例子:

     1 #include "stdafx.h"
     2 
     3 void Function()
     4 {
     5     char a = (char)1;
     6     short b = (short)2;
     7     int c = (int)3;
     8 
     9     char d = (char)c;
    10 }
    11 
    12 int main(int argc, char* argv[])
    13 {
    14     Function();
    15     return 0;
    16 }

      在这个例子中,变量c为int类型,我们定义了一个char类型的变量d,将c赋给d时,前面加个小括号就是明确告诉编译器要把这个int类型的变量c转换成char类型,然后赋给char类型的变量d,这在C语言语法中是合法的,但是是不是所有的类型都可以进行强转呢?来看看下面的例子:

     1 #include "stdafx.h"
     2 
     3 struct Student
     4 {
     5     int hight;
     6     int weight;
     7 };
     8 
     9 void Function()
    10 {
    11     char a = (char)1;
    12     short b = (short)2;
    13     int c = (int)3;
    14 
    15     char d = (char)c;
    16     //加小括号明确告诉编译器我要转换什么类型,编译一下,看这个情况可以不可以
    17     Student e = (Student)c;
    18 }
    19 
    20 int main(int argc, char* argv[])
    21 {
    22     Function();
    23     return 0;
    24 }

      看一看编译信息,看结构体允许这样转不,

       调试信息中,可以看到编译器很明确的告诉我们,无法将int类型转换成struct Student,看来也不是所有的类型之间都可以相互转换~~~

      但是基础类型,char、short、int之间可以相互转换,基础类型向结构体类型转换就不允许了!

    b、带星号(*)类型之间的转换

     1 #include "stdafx.h"
     2 
     3 struct Student
     4 {
     5     int hight;
     6     int weight;
     7 };
     8 
     9 void Function()
    10 {
    11     char* x;
    12     int* y;
    13 
    14     x = (char*)10;
    15     y = (int*)20;
    16 
    17     short* z = (short*)y;
    18     char* a = (char*)y;
    19     int* b = (int*)x;
    20 }
    21 
    22 int main(int argc, char* argv[])
    23 {
    24     Function();
    25     return 0;
    26 }

      再来看看结构体带星类型能不能与普通带星类型进行转换

     1 #include "stdafx.h"
     2 
     3 struct Student
     4 {
     5     int hight;
     6     int weight;
     7 };
     8 
     9 void Function()
    10 {
    11     char* x;
    12     int* y;
    13 
    14     x = (char*)10;
    15     y = (int*)20;
    16 
    17     short* z = (short*)y;
    18     char* a = (char*)y;
    19     int* b = (int*)x;
    20 
    21     Student* student = (Student*)x;
    22     Student* student2 = (Student*)y;
    23     Student* student3 = (Student*)z;
    24 }
    25 
    26 int main(int argc, char* argv[])
    27 {
    28     Function();
    29     return 0;
    30 }

       

       根据编译结果可以看出,是可以的

      这一块的反汇编代码就不贴了,之前在汇编里头,byte、word、dword类型转换的时候都有过测试

    二、&符号的使用

      先不介绍&是怎么用的,什么概念,我们抛出问题例子来看&符号,看看编译器怎么说

     1 #include "stdafx.h"
     2 
     3 void Function()
     4 {
     5     char a = 10;
     6     short b = 20;
     7     int c = 30;
     8 
     9     char d = &a;
    10 }
    11 
    12 int main(int argc, char* argv[])
    13 {
    14     Function();
    15     return 0;
    16 }

      例子中,我们使用char类型的变量d来接受&a的值,我们编译一下

       

       编译器说,没办法将一个char* 类型转换成char类型,看来在变量前面加上了&符号之后,这个变量就成了带*类型

      我们将代码更改成如下:

     1 #include "stdafx.h"
     2 
     3 void Function()
     4 {
     5     char a = 10;
     6     short b = 20;
     7     int c = 30;
     8 
     9     char* d = &a;
    10 }
    11 
    12 int main(int argc, char* argv[])
    13 {
    14     Function();
    15     return 0;
    16 }

       

       这个时候发现编译通过了

      那么,我们在这里不妨来自己定义一下&符号?&是地址符,类型是其后面的类型加一个“*”,任何变量都可以使用&来获取地址,但不能用在常量上。

       

      这下我们可以来回答了,&a是char* 类型,  &b是short* 类型, &c是int* 类型

       再来看看下面的例子

       

       &pa是char** 类型, &pb是short** 类型, &pc是int** 类型

      基本类型的定义探测完了,我们就来看看完整写法

     1 #include "stdafx.h"
     2 
     3 void Function()
     4 {
     5     char a = 10;                
     6     short b = 20;                
     7     int c = 30;                
     8                 
     9     char* pa = (char*)&a;                
    10     short* pb = (short*)&b;                
    11     int* pc = (int*)&c;                
    12     
    13     //简写为:                
    14     char* pa = &a;                
    15     short* pb = &b;                
    16     int* pc = &c;                
    17 
    18 }
    19 
    20 int main(int argc, char* argv[])
    21 {
    22     Function();
    23     return 0;
    24 }
     1 #include "stdafx.h"
     2 
     3 void Function()
     4 {
     5     char a = 10;            
     6     short b = 20;            
     7     int c = 30;            
     8     
     9     char* pa = &a;            
    10     short* pb = &b;            
    11     int* pc = &c;            
    12     
    13     char** ppa = (char**)&pa;            
    14     short** ppb = (short**)&pb;            
    15     int** ppc = (int**)&pc;            
    16     
    17     //简写为:            
    18     char** ppa = &pa;            
    19     short** ppb = &pb;            
    20     int** ppc = &pc;            
    21 }
    22 
    23 int main(int argc, char* argv[])
    24 {
    25     Function();
    26     return 0;
    27 }

    三、“带*类型”的特征探测:求值

        int* px;                    
        
        int** px2;                    
        
        int*** px3;                    
        
        int**** px4;                    
        
        //*(px) 是什么类型?                    
        
        //*(px2) 是什么类型?                    
        
        //*(px3) 是什么类型?                    
        
        //*(px4) 是什么类型?
     1 #include "stdafx.h"
     2 
     3 void Function()
     4 {
     5     int x = 10;
     6     int* px = &x;
     7     int y = *px;
     8             
     9 }
    10 
    11 int main(int argc, char* argv[])
    12 {
    13     Function();
    14     return 0;
    15 }

      反汇编代码如下:

     1 0040D490   push        ebp
     2 0040D491   mov         ebp,esp
     3 0040D493   sub         esp,4Ch
     4 0040D496   push        ebx
     5 0040D497   push        esi
     6 0040D498   push        edi
     7 0040D499   lea         edi,[ebp-4Ch]
     8 0040D49C   mov         ecx,13h
     9 0040D4A1   mov         eax,0CCCCCCCCh
    10 0040D4A6   rep stos    dword ptr [edi]
    11 0040D4A8   mov         dword ptr [ebp-4],0Ah
    12 0040D4AF   lea         eax,[ebp-4]
    13 0040D4B2   mov         dword ptr [ebp-8],eax
    14 0040D4B5   mov         ecx,dword ptr [ebp-8]
    15 0040D4B8   mov         edx,dword ptr [ecx]
    16 0040D4BA   mov         dword ptr [ebp-0Ch],edx
    17 0040D4BD   pop         edi
    18 0040D4BE   pop         esi
    19 0040D4BF   pop         ebx
    20 0040D4C0   mov         esp,ebp
    21 0040D4C2   pop         ebp
    0040D4A8   mov         dword ptr [ebp-4],0Ah      ;将0xA(十进制的10)放到局部变量ebp-4中,这里我们的局部变量定义的是x
    0040D4AF lea eax,[ebp-4]            ;取ebp-4的地址放入eax中 0040D4B2 mov dword ptr [ebp-8],eax      ;将eax的值放入局部变量ebp-8中,这里我们的局部变量定义的是px,它的类型是int*类型 0040D4B5 mov ecx,dword ptr [ebp-8]      ;将ebp-8的值放入到ecx中 0040D4B8 mov edx,dword ptr [ecx]        ;取ecx值所代表的地址中的值放入edx中,也就是取ebp-8(px)的内容并当做地址,取这个地址的内容 0040D4BA mov dword ptr [ebp-0Ch],edx      ;最后将取出来的值放到ebp-0xc中,ebp-0xc是我们的局部变量y
     1 #include "stdafx.h"
     2 
     3 void Function()
     4 {
     5     int x,y;    
     6     int* px;    
     7     int** px2;    
     8     int*** px3;    
     9     
    10     x = 10;    
    11     px = &x;    
    12     px2 = &px;    
    13     px3 = &px2;    
    14     
    15     y = *(*(*(px3)));                
    16 }
    17 
    18 int main(int argc, char* argv[])
    19 {
    20     Function();
    21     return 0;
    22 }

      观察这段代码的反汇编,这里我不做解释了,解释起来很麻烦,也不算是麻烦吧,读者稍微有点汇编底子,相信也不会看我啰嗦

    0040D490   push        ebp
    0040D491   mov         ebp,esp
    0040D493   sub         esp,54h
    0040D496   push        ebx
    0040D497   push        esi
    0040D498   push        edi
    0040D499   lea         edi,[ebp-54h]
    0040D49C   mov         ecx,15h
    0040D4A1   mov         eax,0CCCCCCCCh
    0040D4A6   rep stos    dword ptr [edi]
    0040D4A8   mov         dword ptr [ebp-4],0Ah
    0040D4AF   lea         eax,[ebp-4]
    0040D4B2   mov         dword ptr [ebp-0Ch],eax
    0040D4B5   lea         ecx,[ebp-0Ch]
    0040D4B8   mov         dword ptr [ebp-10h],ecx
    0040D4BB   lea         edx,[ebp-10h]
    0040D4BE   mov         dword ptr [ebp-14h],edx
    0040D4C1   mov         eax,dword ptr [ebp-14h]
    0040D4C4   mov         ecx,dword ptr [eax]
    0040D4C6   mov         edx,dword ptr [ecx]
    0040D4C8   mov         eax,dword ptr [edx]
    0040D4CA   mov         dword ptr [ebp-8],eax
    0040D4CD   pop         edi
    0040D4CE   pop         esi
    0040D4CF   pop         ebx
    0040D4D0   mov         esp,ebp
    0040D4D2   pop         ebp
    0040D4D3   ret

      总结:

      1、带*类型的变量,可以通过在其变量前加*来获取其指向内存中存储的值.

      2、在带*类型的变量前面加*,类型是其原来的类型减去一个*.

    四、用指针操作数组

        char arr[10];                
                    
        char* p = &arr[0]; //取数组第一个元素的地址                
        char* p2 = arr;    //简写

      看看实例吧

     1 #include "stdafx.h"
     2 
     3 void CharArray()
     4 {
     5     char arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};                
     6                 
     7     char* p = &arr[0]; //取数组第一个元素的地址                
     8     //char* p2 = arr;    //简写
     9     for (int i = 0; i < 10; i ++)
    10     {
    11         printf("%d ", *(p + i));
    12     }
    13     printf("
    ");
    14 }
    15 
    16 void ShortArray()
    17 {
    18     short arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};                
    19                 
    20     short* p = &arr[0]; //取数组第一个元素的地址                
    21     //char* p2 = arr;    //简写
    22     for (int i = 0; i < 10; i ++)
    23     {
    24         printf("%d ", *(p + i));
    25     }
    26     printf("
    ");
    27 }
    28 
    29 void IntArray()
    30 {
    31     int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};                
    32                 
    33     int* p = &arr[0]; //取数组第一个元素的地址                
    34     //char* p2 = arr;    //简写
    35     for (int i = 0; i < 10; i ++)
    36     {
    37         printf("%d ", *(p + i));
    38     }
    39     printf("
    ");
    40 }
    41 
    42 int main(int argc, char* argv[])
    43 {
    44     CharArray();
    45     ShortArray();
    46     IntArray();
    47     return 0;
    48 }

      总结:

      1、&arr[0]代表取数组中第一个元素的地址,可以省略为数组名.

      2、*(p+i) = p[i]

       

      将数组中的值进行倒置,利用指针

     1 #include "stdafx.h"
     2 
     3 void Function()                    
     4 {                    
     5     int arr[5] = {1, 2, 3, 4, 5};
     6     int length = 5;
     7     int* parr = arr;
     8     int* pfirst = arr;
     9     int* pend = &arr[length-1];
    10                     
    11     //..此处添加代码,使用指针,将数组的值倒置
    12     for (; pfirst <= pend; pfirst ++, pend --)
    13     {
    14         int temp = *pend;
    15         *pend = *pfirst;
    16         *pfirst = temp;
    17     }
    18 
    19                         
    20     //打印数组值的代码已经写完,不需要修改
    21     for(int k=0; k < 5; k ++)                
    22     {                
    23         printf("%d ", *(parr + k));            
    24     }
    25     printf("
    ");                    
    26 }                    
    27 
    28 
    29 int main(int argc, char* argv[])
    30 {
    31     Function();
    32     return 0;
    33 }
  • 相关阅读:
    centos7下安装docker
    java中获取两个时间中的每一天
    Linq中string转int的方法
    logstash 主题综合篇
    Windows环境下ELK(5.X)平台的搭建
    本地没问题 服务器 提示 Server Error in '/' Application
    错误 未能找到类型或命名空间名称"xxxxxx"的真正原因
    System.web和System.WebServer
    Chrome Adobe Flash Player 因过期而 阻止
    请求WebApi的几种方式
  • 原文地址:https://www.cnblogs.com/Reverse-xiaoyu/p/11749789.html
Copyright © 2011-2022 走看看