王学岗c语言指针和指针运算

来源:互联网 发布:指南针炒股软件收费版 编辑:程序博客网 时间:2024/05/16 04:50

关于指针有一片文章写的详尽又容易了解:http://blog.chinaunix.net/uid-22889411-id-59688.html

(1)指针和地址的区别
//指针有类型 地址没有类型,需要强制类型转化才能赋值给指针变量

int* p=(int*)0x44fc28

(2)指针使用之前必须要有初始值

void main(){    int* p;    //报空指针异常    printf("%#x",p);    getchar();}

上文报错处可以这样写

int* p=NULL;

(3)指针变量多次赋值为不同变量的地址

void main(){    int* p=NULL;    printf("%#x",p);    //200当做一个内存地址赋值给了指针变量(16进制)    p = 200;    //打印指针变量对应的值    printf("%d\n", *p);    getchar();}

打印输出发现报错
200转成16进制,由于数字比较小,系统本身已经占用了这块内存区域,内存地址已经被分配掉了,然而系统本身内存数据不允许访问!一般情况下,我们不要直接给指针变量赋值为整数。
(4)NDK指针地址,二级指针

int a=100;    int b=200;    int* p1=&a;     //p1保存的是a变量的地址——0x0022FDE0,通过该地址可以查询到a的值是100    printf("p1地址:%#x\n",&p1);    //指针变量也是变量,同样占据了内存空间,同样有地址,因此可以用一个指针指向它    //这就称之为二级指针,    //定义一个二级指针p2,&p1指针的地址    int** p2=&p1;    **p2=1000;    printf("二级指针的地址:%#x",&p2);    //a的值会变成1000,*是取值,&是取地址    //p2保存的数据是p1的地址,*p2上的数据是p1上面的数据    //p1保存的数据是a的地址,所以**p2实际上就是a的值    printf("\na的值:%d",a);        system("pause");

这里写图片描述

(4)指针运算(赋值运算符和算术运算)
算术运算(+,-,*,/)

void main(){    int ids[]= {22,33,34,44,34,46,22,90};    //打印数组    printf("数组%#x\n",ids);    //数组第一个元素地址    printf("数组第一个元素地址 %#x",&ids[0]);    //两个值相同    system("pause");}

控制台输出两个值相同
ids是常量指针,存储的是数组的首地址

继续大家会发现,数组在内存中的存储是连续的
这里写图片描述
我们 看下指针如何运算:

void main(){    int ids[] = { 22, 33, 34, 44, 34, 46, 22, 90 };    //打印数组    printf("数组%#x\n", ids);    //数组第一个元素地址    printf("数组第一个元素地址 %#x\n", &ids[0]);    //两个值相同    int* p = ids;    p++;    printf("地址:%#x值:%d",p,*p);    system("pause");}

注意,p++后,*p的值变成了33(既数组的第二个元素),地址也变成了第二个元素的地址,因为int类型占4个字节,+1后就相当于+了一个int字节数,就是字节由de8+4=dec;
这里写图片描述

总结:p++每次向前移动sizeof(数据类型)个字节
下面我使用指针遍历数组

void main(){    int ids[] = { 22, 33, 34, 44, 34, 46, 22, 90 };    //打印数组    printf("数组%#x\n", ids);    //数组第一个元素地址    printf("数组第一个元素地址 %#x\n", &ids[0]);    //两个值相同    int* p = ids;    p++;    printf("地址:%#x值:%d\n",p,*p);    for (; p < ids + 8;p++){        printf("值:%d\n",*p);    }    system("pause");}

这里写图片描述

注意:让指针递增或者递减,一般情况下只有在数组遍历的时候才有意义,是基于数组在内存中的象形排列方式;
(5)指针运算(通过使用指针循环给数组赋值)
传统方法赋值

void main(){    int ids[6] ;    int*p = ids;    //传统的写法赋值    int i = 0;    for (; i < 6; i++){        ids[i] = i * 2;    }    //输出    i = 0;    for (; i < 6; i++){        printf("值:%d",ids[i]);    }    system("pause");}

这里写图片描述
指针赋值:

void main(){    int ids[6] ;    int*p = ids;    int i = 0;    for (; p < ids + 6;p++){        *p = i * 2;        i++;    }    i = 0;    for (; i < 6; i++){        printf("值:%d",ids[i]);    }    system("pause");}

运行结果和上次运行结果一样;

(6)指针运算,数组内部的加减

void main(){    int ids[] = {34,5,65,43,66,77,99};    int* p = ids;    p = p + 3;    //*p的值是43    printf("值:%d\n地址:%#x\n",*p,p);    system("pause");}

(7)指针运算指针大小比较
大小比较,都是在遍历数组的时候运用,其他情况下没用,指针地址相等,并不代表值相等;因为指针有类型
(8)NDK-指针运算-指针与数组的几种写法

int _tmain(int argc, _TCHAR* argv[]){    int ids[]={52,84,86,92,48,47,15,32};    int i=0;    for(;i<7;i++){    //输出数据        printf("%d  %#x\n",ids[i],&ids[i]);        //ids就是常亮指针,就是一个首地址        //ids+0等价于 &ids[0]        //ids+1等价于 &ids[1]        //以此类推……        //ids+i 等价于&ids[i]        //在地址墙面加*就是取值,所以        //*(ids+i) 等价于 ids[i]        printf("%d  %#x\n",*(ids+i),ids+i);    }    return 0;}

这里写图片描述

(9)指针引用二维数组

int _tmain(int argc, _TCHAR* argv[]){    //两行三列的二维数组    int ids[2][3]={23,58,4,58,69,79};    //遍历二维数组,外层循环控制行,内存循环控制列    int i=0;    for(;i<2;i++){    int j=0;    for(;j<3;j++){        printf("值:%d,地址:%#x  ",ids[i][j],& ids[i][j]);    }    //换行    printf("\n");    }    printf("ids:%#x   &ids:%#x  *ids:%#x ",ids,&ids,*ids);    getchar();    return 0;}

这里写图片描述
大家看下,我们发现ids,&ids,*ids的三个地址是一模一样。注意,地址相同,但并不代表值相同

int _tmain(int argc, _TCHAR* argv[]){    //两行三列的二维数组    int ids[2][3]={23,58,4,58,69,79};    //遍历二维数组,外层循环控制行,内存循环控制列    int i=0;    for(;i<2;i++){    int j=0;    for(;j<3;j++){        printf("值:%d,地址:%#x  ",ids[i][j],& ids[i][j]);    }    //换行    printf("\n");    }    printf("ids:%#x   &ids:%#x  *ids:%#x\n ",ids,&ids,*ids);    printf("长度%d,        长度%d,          长度%d",sizeof(*ids),sizeof(*&ids),sizeof(**ids));    getchar();    return 0;}

大家看下打印结果:
这里写图片描述
大家注意了,长度12说明ids代表行指针(指向一个拥有三个数组的元素),每行3个int类型,每个int类型是4个字节;
长度24说明&ids代表的是一个二维数组指针,24个int类型,每个int类型4个字节;
长度4,说明*ids代表数组的类型,指向该数组的数据类型的指针;如果是double类型的数组,则此处将是8;

再看下下面的代码

int _tmain(int argc, _TCHAR* argv[]){    //两行三列的二维数组    int ids[2][3]={23,58,4,58,69,79}; //打印结果是第一行的第一个元素23,即ids[0][0] printf("值:%d",**ids);    getchar();    return 0;}

我们继续来推导,看下面的代码

int _tmain(int argc, _TCHAR* argv[]){    //两行三列的二维数组    int ids[2][3]={23,58,4,58,69,79};    //打印第二行,第二列    printf("值:%d\n",ids[1][1]);    //用指针来打印第二行,第二列    printf("值%d",*(*(ids+1)+1));    getchar();    return 0;}

ids代表行指针:ids+0代表第一行,
ids+1代表第二行,
以此类推,第N行为ids+n;

取某一行的第一个元素的指针:*(ids+i)
第一行第一个元素指针:*(ids+0)
第二行第一个元素指针:*(ids+1)
以此类推:*(ids+i)

ids代表首地址所以
取第一行第一个指针:*ids+0;
取第一行第二个指针:*ids+1;
取第一行第三个指针:*ids+2;
以此类推:*ids+j

把以上两个推理结合下,取第二行第二个元素的指针:
*(ids+1)+1
我们可以得出结论:(ids+i)+j,获取该地址的值为(*(ids+i)+j)

0 1
原创粉丝点击