从一道笔试题来看指针的使用

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

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}

 。 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。loading。。。。。。。。。。。。。。。。。。。。。。。。
如果您分析的结果和程序运行的结果都一致,那么下面的内容您可以忽略了,...o(∩_∩)o...

如果对上面的程序一头雾水的话,个人建议那最好看一下下面的内容了。.......o(∩_∩)o...

 

指针是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(指针所指向变量的类型)。

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

首先在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。

 

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页