指针数组和数组指针的使用

来源:互联网 发布:淘宝优惠券免费领取 编辑:程序博客网 时间:2024/05/21 21:28

指针数组:指针的数组,表示一个数组,并且数组的每一个元素都是指针类型。

数组指针:数组的指针,表示一个指针,并且是指向数组的指针。


不运行程序,问下面代码的输出是什么?

1#include<iostream>
2 using namespace std;
3 int main()
4 {
5     char *str[]={"welcome","to","Fortemedia","Nanjing"};
6     char**p=str+1;
7     str[0]=(*p++)+2;
8     str[1]=*(p+1);

9     str[2]=p[1]+3;
10   str[3]=p[0]+(str[2]-str[1]);
11   cout<<str[0]<<endl;
12   cout<<str[1]<<endl;
13   cout<<str[2]<<endl;
14   cout<<str[3]<<endl;

15   system("pause");

16}

 

指针是c/c++语言中一个重要的语言特性,但对于c/c++的初学者来说,却不是那么好理解。总起来说指针一个特殊的变量,这个变量能合法的使用*操作符对指针的变量内容进行提领(dereference)和成员访问。对于指针变量在它四个字节(32位平台)的内存里存储的数据是一个内存的地址值,也就是我们平时说的指向一个地址,而指针变量的类型则决定着对指针变量的所指向的地址里的数据的访问方式和从指向的地址开始往下所涵盖的范围。举例来说:

#include<iostream>
using namespace std;

int main()
{
    int i[2]={1073741824,-1073741824};
    int *p1=&i[0];
    char *p2=(char*)&i[0];
    float *p3=(float*)&i[0];
    printf("%d->%d/n",p1,*p1);
    printf("%d->%d/n",p2,*p2);
    printf("%d->%f/n",p3,*p3);
    p1++;
    p2++;
    p3++;
    printf("%d->%d/n",p1,*p1);
    printf("%d->%d/n",p2,*p2);
    printf("%d->%f/n",p3,*p3);

    system("pause");

}

上述代码中指针变量p1,p2,p3指向相同的地址值,都是i[0]所标识的内存的地址值,但由于指针的类型不同,导致用*运算符进行提领时,*p1,*p2,*p3的值不一样。当p1用*提领p1所指向的内存里的数据时,由于p1是int*型的,所以会从地址值为&i[0]开始,往下涵盖四个字节(sizeof(int))的内存,然后把里面的数据安照int变量的存储方式解析成一个int型数值。1073741824在内存&i[0]~&i[0]+3中存储是0x00,0x00,0x00,0x40,(小段机 补码存储),所以*p1的值是1073741824。而p2是char*型的,所以仅从地址值为&i[0](sizeof(char))的内存把里面的数据按照char变量的存储方式解析成一个char型数值,由于地址值为&[i]的内存里是0x00,所以*p2为0.同样由于p3是float*型的,所以会从地址值为&i[0]开始,往下涵盖四个字节(sizeof(float))的内存,然后把里面的数据安照float变量的存储方式解析成一个float型数值。由于float型变量的存储方式不同于整型,c/c++浮点数存储遵循ieee标准,按照标准*p3的值为2.0(具体请参见本博客里一篇关于float内存布局的博文,不再赘述)。另外从上述代码我们可以看到,指针变量的类型还影响着指针变量算术运算时的跨度,即指针变量+1时,指针变量的值会增加sizeof(指针所指向变量的类型)。

弄明白上面所分析的是掌握指针的关键(个人是这么看的),基于刚才的分析来看开始的笔试题:

#include <iostream>using namespace std;int main ( ){    char *str[]={"welcome","to","fortemedia","Nanjing"};    char * * p=str+1;     //p指向 "to"字符串地址        str[0]=(*p++) +2;          //str[0]指向'\0';           然后p后移 p=str[2]    str[1]=*(p+1);            //p+1后 p+1 = str[3];   然后 str[1] = str[3]             str[2]=p[1]+3;             //str[2]指向str[3]的从0开始数的第三个 str[2]指向"jing"地址    str[3]=p[0]+(str[2]-str[1]);  //str[3]指向从p[0]开始(也就是*p,也就是str[2])的 偏移量为(str[2]-str[1])的地址~ str[2]指向"jing",str[1]指向str[3],也就是"Namjing",所以str[3]指向"jing"的"g"地址    printf("%s\n",str[0]);    printf("%s\n",str[1]);    printf("%s\n",str[2]);    printf("%s\n",str[3]);        return 0;}


int main(){    char *str[] = {"Welcome","to","Fortemedia","Nanjing"};     char **p = str + 1;         str[0] = *p++; //{"to","to","Fortemedia","Nanjing"};    str[1] = *(p+1); //{"to","Nanjing","Fortemedia","Nanjing"};    str[2] = p[1] + 3; //{"to","Nanjing","jing","Nanjing"};    str[3] = p[0] + (str[2] - str[1]); //str[2]-str[1]是原来的指向Nanjing中的j的指针减去Nanjing中的N的指针,当然是3了//p[0] 是指向"jing"中的j的,再加3就是g了        printf("%s\n",str[0]);     printf("%s\n",str[1]);     printf("%s\n",str[2]);     printf("%s\n",str[3]);     return 0;}

看罢以上两位大牛的分析,大概大家也都明白了。

首先在line 5声明一个指针数组,而str的值就是数组的起始地址值,str的值被默认解析成char **变量的值。

line6声明了一个2级指针,char**p=str+1;由于str是char**型,即str指向的类型是char *型的,所以p的值是(int)str+sizeof(char*),显然p指向了str的第二个元素即str[1]的地址。

line7 :(*p++)+2;,由于后置运算符++优先级比*高,所以先进行++运算,p的值变为(int)p+sizeof(char*),,显然此时p指向了str[2]的地址,再进行*运算,由于后置是++返回未变化的p的值,取到了str[1]的值,即指向字符串"to"的指针的值,由于*p类型是char*的所以](*p++)+2;最终str[0]指向了“to”结尾的'/0'所以输出str[0]时为空。

line8:str[1]=*(p+1);,显然str[1]指向了字符串"Nanjing"的首地址。cout<<str[1]<<endl;输出字符串Nanjing

line9:很显然cout<<str[2]<<endl;输出jing

line10:由于在line7分析到p指向了str[2]的地址,由于line9中,把&str[2]~&str[2]+3里的数据修改成了字符创"jing"的首地址。所以最终cout<<str[3]<<endl; 输出g。

更为形象的分析,可以参考 http://blog.csdn.net/rein07/article/details/6708730 的博客,里面有图解。



参考:http://blog.csdn.net/Demon__Hunter/article/details/4140603   demon__hunter

http://blog.csdn.net/rein07/article/details/6708730   rein07

原创粉丝点击