c语言指针之二级指针示例

所属分类: 软件编程 / C 语言 阅读数: 115
收藏 0 赞 0 分享

二级指针的概念

首先任何值都有地址,一级指针的值虽然是地址,但这个地址做为一个值亦需要空间来存放,是空间就具有地址,这就是存放地址这一值的空间所具有的地址,二级指针就是为了获取这个地址,一级指针所关联的是其值(一个地址)名下空间里的数据,这个数据可以是任意类型并做任意用途,但二级指针所关联的数据只有一个类型一个用途,就是地址,指针就是两个用途提供目标的读取或改写,那么二级指针就是为了提供对于内存地址的读取或改写指针的表现形式是地址,核心是指向关系指针运算符“*”的作用是按照指向关系访问所指向的对象.如果存在A指向B的指向关系,则A是B的地址,“*A”表示通过这个指向关系间接访问B.如果B的值也是一个指针,它指向C,则B是C的地址,“*B”表示间接访问C如果C是整型、实型或者结构体等类型的变量或者是存放这些类型的数据的数组元素,则B(即C的地址)是普通的指针,称为一级指针,用于存放一级指针的变量称为一级指针变量。A(即B的地址)是指向指针的指针,称为二级指针,用于存放二级指针的变量称为二级指针变量.根据B的不同情况,二级指针又分为指向指针变量的指针和指向数组的指针

二级指针的分类

指向指针变量的指针

在如上的A指向B、B指向C的指向关系中,如果A、B、C都是变量,即C是普通变量,B是一级指针变量,其中存放着C的地址,A是二级指针变量,其中存放着B的地址,则这3个变量分别在内存中占据各自的存储单元,它们之间的相互关系下图所示,相互之间的前后位置关系并不重要.此时,B是一级指针变量,B的值(即C的地址)是一级指针数据;A是二级指针变量,A的值(即B的地址)是二级指针数据.

指向数组的指针

在C语言中,数组与其它变量在使用上有很大的不同.无论是字符型、整型、实型变量,还是结构体类型或者指针类型的变量,语句中出现变量名都代表对该变量所在内存单元的访问,变量名代表整个变量在内存中的存储单元,可以向该变量赋值,也可以从中取出数据使用.但是定义一个数组之后,数组名并不代表整个数组所占据的内存单元,而是代表数组首元素的地址.

二级指针例子:

复制代码 代码如下:

int *q;   //定义一个一级指针变量,它指向一个普通变量(即它存的是一个变量的地址)
int **p;   //定义一个二级指针变量,它指向一个指针变量(它存的也是一个变量地址,只不过是一个指针变量的地址)
int s;
q = &s;   //q中存的是整型变量s的地址,所以q是一级指针
p = &q;   //p中存的是一级指针q的地址,所以p是二级指针

例子:

复制代码 代码如下:

# include <stdio.h>
void f(int ** q);
int main(void)
{
    int i = 9;
    int * p = &i;// int  *p;  p = &i;
    printf("%p\n", p);
    f(&p);
    printf("%p\n", p);

    return 0;
}
void f(int ** q)
{
    *q = (int *)0xFFFFFFFF;// 这里是更改了p的值,与i无关,p不再指向i
}


1、二级指针的相关问题
复制代码 代码如下:

#include "iostream"
#include "string"
#include "cmath"
using namespace std;
int main()
{
char ch='a';
char *p1=&ch;
char **p=&p1;
cout<<ch<<endl;
cout<<p1<<endl;
cout<<&ch<<endl;
cout<<*p1<<endl;
cout<<p<<endl;
cout<<**p<<endl;
char *p3=NULL;
//cout<<p3<<endl;
//cout<<*p3<<endl;
char **p4=&p3;
cout<<p4<<endl;
//cout<<*p4<<endl;
cout<<**p4<<endl;
}

思考上面的输出是什么?

2、如下程序,输出是什么?

复制代码 代码如下:

#include "iostream"
using namespace std;
int main()
{
int a=12;
int *p=&a;
int **p1=&p;
cout<<a<<endl;
cout<<&a<<endl;
cout<<p<<endl;
cout<<*p<<endl;
cout<<p1<<endl;
cout<<*p1<<endl;
cout<<**p1<<endl;
}

3、如下程序的输出是什么?

复制代码 代码如下:

#include "iostream"
using namespace std;
int main()
{
int *p=NULL;
int **p1=&p;
cout<<p<<endl;
//cout<<*p<<endl;
cout<<p1<<endl;
cout<<*p1<<endl;
cout<<**p1<<endl;
}
void GetMM(char **p,int n){
if(*p!=NULL)
*p=(char*)malloc(n);
(*p)[1]='a';
}
int main()
{
char *str=NULL;
GetMM(&str,10);
}
#include "iostream"
using namespace std;
union A{
int b;
char ch[2];
};
int main()
{
A a;
a.ch[0]=0x38;
a.ch[1]=0x39;
printf("%x",a.b);//3938
}

更多精彩内容其他人还在看

用标准c++实现string与各种类型之间的转换

这个类在头文件中定义, < sstream>库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本
收藏 0 赞 0 分享

C++如何通过ostringstream实现任意类型转string

再使用整型转string的时候感觉有点棘手,因为itoa不是标准C里面的,而且即便是有itoa,其他类型转string不是很方便。后来去网上找了一下,发现有一个好方法
收藏 0 赞 0 分享

C/C++指针小结

要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区
收藏 0 赞 0 分享

C++ 类的静态成员深入解析

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象
收藏 0 赞 0 分享

C++类的静态成员初始化详细讲解

通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化
收藏 0 赞 0 分享

C++类静态成员与类静态成员函数详解

静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值
收藏 0 赞 0 分享

C++中的friend友元函数详细解析

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样
收藏 0 赞 0 分享

static全局变量与普通的全局变量的区别详细解析

以下是对static全局变量与普通的全局变量的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
收藏 0 赞 0 分享

C++ explicit关键字的应用方法详细讲解

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?下面就让我们一起来看看这方面的知识吧
收藏 0 赞 0 分享

教你5分钟轻松搞定内存字节对齐

随便google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则
收藏 0 赞 0 分享
查看更多