一、指针的概念
在程序中,我们所定义的变量,都要在内存中占有一个可标识的存储区域。每一个存储区域由若干个字节组成,在内存中每一个字节都有一个“地址”,一个存储区域的“地址”指的是存储区域中第一个字节的地址。
指针是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”,意思是说通过它能找到以它为地址的内存单元。
指针并不是用来存储数据的,而是用来存储数据在内存中地址,它是内存数据的快捷方式,通过这个快捷方式,即使你不知道这个数据的变量名也可以操作它。
二、指针与指针变量
2.1 直接访问与间接访问
直接访问:通过变量名或地址访问程序中一个实体的存储空间方式(直接通过定义的变量来获取变量的数值)
间接访问:通过把地址存放在一个变量中,然后通过先找出地址变量中值,再由此地址找到最终要访问的变量的方法(通过指针的形式,指向原来变量存储的值)
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! 定义一个整形变量
int num = 5;
//! 定义一个指针
int *p = #
//! 直接访问形式,就是直接通过原来的变量名来进行访问
qDebug("%d",num);
//! 间接的访问形式,就是间接通过指针指向的变量,来间接的访问原来变量的,此处的*为指向的意思
qDebug("%d",*p);
return a.exec();
}
输出为:
5
5
2.2 p、*p和&p的区别
p是一个指针变量的名字,表示此指针变量指向的内存地址。
*p表示此指针指向的内存地址中存放的内容,一般是一个和指针类型一致的变量或者常量。
&p就是取指针p的地址。
&p和p有什么区别?
区别在于,指针p同时也是个变量,既然是变量,编译器肯定要为其分配内存地址,就像程序中定义了一个int型的变量i,编译器要为其分配一块内存空间一 样。而&p就表示编译器为变量p分配的内存地址,而因为p是一个指针变量,这种特殊的身份注定了它要指向另外一个内存地址,程序员按照程序的需要 让它指向一个内存地址,这个它指向的内存地址就用p表示。而且,p指向的地址中的内容就用*p表示。
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! 定义一个变量
int num = 5;
//! 定义一个指针
int *p;
p = #
// *p = 5;
//! 定义个二级指针
int **pp;
pp = &p;
//! 输出变量num的地址
qDebug("num address=%x",&num);
qDebug("num address=%x",p);
qDebug("num value=%x",*p);
qDebug("p address =%x",&p);
return a.exec();
}
输出:
num address=e3b2f850
num address=e3b2f850
num value=5
p address =e3b2f858
2.3 *和&运算
先理解地址和数据,想象内存里面是一个个的小盒子,每个盒子对应一个编号,这个编号就是地址,盒子里存放的就是数据。
&是取地址运算符,如有 int a; 即有一个小盒子里面存放的数据起名叫a,&a就是取a的地址,即该盒子的编号。
*(地址)是取值运算符,这里*是解引用操作符,可以理解成打开对应地址编号的盒子,取出里面的数据。*(&a) 就是打开a对应的小盒子,取出里面的数据,即*(&a)和a等价。
(*p)操作是这样一种运算,返回p 的值作为地址的那个空间的取值。
(&p)则是这样一种运算,返回当时声明p 时开辟的地址。
2.4 *&p和&*p区别
根据运算优先级,*&p 等价于*(&p)。&*p 等价于&(*p)。
1、如果p是int *指针变量,那么*&p = p,&*p = p,都是p。
2、如果p是一个int变量,那么*&p = p;而&*p是非法的,因为*p非法。
比如int p =10;那么*&p = *(&p) = p = 10(即从p的地址取值),而&*p = &(*p) 则非法,因为p=10,*10是取内存地址为10的值,这在c语言中是不合法的。
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! 定义一个变量
int num = 5;
//! 定义一个指针
int *p;
p = #
// *p = 5;
//! 定义个二级指针
int **pp;
pp = &p;
//! 输出变量num的地址
qDebug("p address =%x",*(&p));
qDebug("p address =%x",&(*p));
return a.exec();
}
输出:
p address =6ff6f900
p address =6ff6f900
2.5 指针与指针变量区别
系统为每一个内存单元分配一个地址值,C/C++把这个地址值称为“指针”。如有int i=5;,存放变量i的内存单元的编号(地址)&i被称为指针。
“指针变量”则是存放前述“地址值”的变量,也可以表述为,“指针变量”是存放变量所占内存空间“首地址”的变量(因为一个变量通常要占用连续的多个字节空间)。比如在int i=5;后有一句int *p=&i;,就把i的指针&i赋给了int *型指针变量p,也就是说p中存入着&i。所以说指针变量是存放指针的变量。
有一个事实值得注意,那就是有不少资料和教科书并没有如上区分,而是认为“指针是指针变量的简称”,如对int *p=&i;的解释是:声明一个int *型指针p,并用变量i的地址初始化;而严格说应该是声明一个int *型指针变量p才对。所以有时看书要根据上下文理解实质,而不能过于拘泥于文字表述。
2.6 一级指针与二级指针
我们定义一个指针变量int *p; p是指针变量,专门用来存放地址。
int *p=&a;相当于int *p; p=&a;
p存放的是a的地址,*p也等价于 a。指针变量p既然是变量,也同变量a一样对应一个小盒子,也有一个地址编号,&p就是取指针p的地址。这样就好理解二级指针了。
*p和**p的区别
int *p :一级指针,表示p所指向的地址里面存放的是一个int类型的值
int **p :二级指针,表示p所指向的地址里面存放的是一个指向int类型的指针(即p指向的地址里面存放的是一个指向int的一级指针)
例:
int a=5; //定义整形变量
int *p=&a; //定义一个指针指向这个变量
int **p1=&p; //定义一个二级指针指向p指针
以上3行输出的值都是5 。
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! 定义一个变量
int num = 5;
//! 定义一个指针
int *p;
p = #
// *p = 5;
//! 定义个二级指针
int **pp;
pp = &p;
//! 输出变量num的地址
qDebug("%x",**pp);
return a.exec();
}
输出:
5
2.7 sizeof(p) 与 sizeof(*p)
对于任何指针变量p,变量p本身就是指针,它的大小就是指针的大小。p是p指向的,而*p的大小是被指向的大小。
sizeof(p)是指针本身的大小。这取决于地址总线的大小。这意味着对于64位系统,地址总线大小将是64位(8字节),因此指针将是8字节长(这表明您的系统是64位)。在32位系统上,它的大小是32位(4字节)。
如果sizeof(*p)返回的是p所指向的大小,那么您就知道int的大小(在您的例子中p指的是)是4字节,这在32位和64位系统上都是正常的。
例子1:
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! 定义一个变量
int num = 5;
//char num = 5;
//! 定义一个指针
int *p;
p = #
qDebug("size of int = %d",sizeof(int));
qDebug("size of p = %d",sizeof(p));
qDebug("size of *p = %d",sizeof(*p));
return a.exec();
}
输出:
size of int = 4
size of p = 8
size of *p = 4
例子2:
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! 定义一个变量
//int num = 5;
char num = 5;
//! 定义一个指针
char *p;
p = #
//! 输出变量num的地址
qDebug("size of char = %d",sizeof(char));
qDebug("size of p = %d",sizeof(p));
qDebug("size of *p = %d",sizeof(*p));
return a.exec();
}
输出:
size of char = 1
size of p = 8
size of *p = 1
例子3:
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! 定义一个数组
int array[10]={1,2,3,4};
//! 定义一个指针
int *p = array;
qDebug("sizeof of array = %d\n",sizeof(array)/sizeof(array[0]));
qDebug("sizeof of array = %d\n",sizeof(p)/sizeof(*p));
return a.exec();
}
输出:
sizeof of array = 10
sizeof of array = 2
2.8 指针初始化
1. 0 值常量表达式,例如,在编译时可获得 0 值的整型 const对象或字面值常量 0。
2. 类型匹配的对象的地址。
3. 另一对象末的下一地址。
4. 同类型的另一个有效指针。
把 int 型变量赋给指针是非法的,尽管此 int 型变量的值可能为 0。但允许把数值 0 或在编译时可获得 0 值的 const 量赋给指针:
int ival;
int zero = 0;
const int c_ival = 0;
int *pi = ival; // error: pi initialized from int value of ival
pi = zero;// error: pi assigned int value of zero
pi = c_ival;// ok: c_ival is a const with compile-time value of 0
pi = 0;// ok: directly initialize to literal constant 0 [1]
除了使用数值 0 或在编译时值为 0 的 const 量外,还可以使用 C++ 语言从 C 语言中继承下来的预处理器变量 NULL,该变量在 cstdlib头文件中定义,其值为 0。如果在代码中使用了这个预处理器变量,则编译时会自动被数值 0 替换。因此,把指针初始化为 NULL 等效于初始化为 0 值 [1]
:
// cstdlib #defines NULL to 0
int *pi = NULL; // ok: equivalent to int *pi = 0; [1]
2.9 const 指针
2.9.1 指向常量的指针变量
定义:const 数据类型 *指针变量名 或 数据类型 const *指针变量名
const char *p;
p = "abcd";
//! 错误,指针指向的对象是一个常量,不能被赋值
p[2] = 'e';
//! 正常,可以修改指针变量p的值
p='ghjk';
注意:指针变量指向的对象的值不能被改变,而指针变量的值可以改变(可以改变指向),本质是指向内容是常量,而指针还是变量。
2.9.2 指向变量的指针常量
定义:数据类型 * const 指针常量名
char str[]="abcd";
char *const p=str;
//! 正确,指针p指向的对象是一个变量
p[3] = 'e';
//! 错误,指针p指向对象是一个常量
p="ghjk";
注意:指针常量的值不能修改,而指针常量所指向的值是可以修改的,本质指针是常量,而指向内容是变量。
2.9.3 指向常量的指针常量
定义 :const 数据类型 * const 指针常量
char str[]="abcd";
const char * const p = str;
//! 错误,指针常量所指向的对象是一个常量
p[3]='e';
//! 错误,指针常量是一个常量
p="ghjk";
注意:指针常量的值和指针常量所指向的对象的值均不能改变。
2.10 void指针类型
void指针类型,可以用来指向一个抽象类型的数据,在将它的值赋给另一个指针变量时,要进行强制类型转换使之适合于赋值的变量的类型。
char *p1;
void *p2;
p1 = (char *)p2;//! (char *)表示强制转换成,强制将空指针转换成字符型指针
2.10 int *p = 5对不对?
5是int型,p是int *型,等号两边类型不匹配。
写成int *p=(int *)5;就对了。把整数5 强制类型转换为整型指针, 在赋值给整型指针p,这个时候p 指向 地址 0x00000005 所表示的内存空间
三. 指针与数组
3.1 一维数组的指针表示方法
a[i] 下标法
*(a+i) 地址法
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! 定义一维数组
int array[] = {1,3,5,7,9};
//! 定义指针
int *p;
//! 下标法
for (int i = 0; i < 5; i++){
qDebug("array1 = %d",array[i]);
}
//! 地址法
for(int i = 0; i < 5; i++){
qDebug("%array2 = %d",*(array+i));
}
//! 指针法
/*for (p = array; p < array+5; p++)
{
qDebug("array3=%d",*p);
}*/
/* p = array;
for (int i = 0; i < 5; i++,p++){
qDebug("array3=%d",*p);
}*/
for (int i = 0; i < 5; i++){
qDebug("array3=%d",*(p+i));
}
return a.exec();
}
以上几种表示方法均可以,但如下几种方式不可以,因为a的值是数组首地址,它是一个常数,其值是不能自增的。指针p是变量,p的值可以不断变化,而p的值是地址,因此p可以不断改变其指向。
for (int i = 0; i < 5; i++){
qDebug("array=%d",a++);
}
3.2 二维数组的指针表示方法
含义 | 表示形式 | 备注 |
第0行第1列元素地址 | a[0]+1,*a+1,*(a+0)+1,&a[0][1] | |
第0行第1列元素的值 | *(a[]0]+1),*(*a+1),a[0][1] |
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int array[2][2]={1,2,3,4};
int *p;
for (p=array[0];p<array[0]+4;p++){
qDebug("array=%d",*p);
}
for (p=*array;p<*array+4;p++){
qDebug("array=%d",*p);
}
for (p=&array[0][0];p<&array[0][0]+4;p++){
qDebug("array=%d",*p);
}
return a.exec();
}
指针的类型取决于它所指向的对象,如果将p=a[0]改写成p=a就会出错,虽然是a[0]和a的值相同,但是a是二级指针,而a【0】是一级指针,二者的指向的对象不同,类型不同;
二维数组中的一级指针和二级指针可以用行指针和列指针来说明,二级指针(数组名)指向行,一级指针用来指向的是某行的中的列。指向行和指向列的指针不是同一类型的指针。
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int array[2][2]={1,2,3,4};
int (*p)[2];
p =array;
for (int i = 0; i < 2; i++){
for (int j = 0; j < 2; j++){
qDebug("array=%d",*((*p+i)+j));
}
}
return a.exec();
}
上列中p是指向行的指针变量,因此应该赋予它行地址,于是p=a是合法的。
3.3 指针与字符数组
字符串是存放在字符数组中的。因此为了对字符串操作,可以定义一个字符数组,也可以定义一个字符指针,通过指针的指向来访问所需要的字符。
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
char string[]="C Language";
char *p;
p = string;
qDebug("%s",string);
qDebug("%s",p);
return a.exec();
}
常用的字符串函数:
1 | strcpy(s1, s2); 复制字符串 s2 到字符串 s1。 |
2 | strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾。 |
3 | strlen(s1); 返回字符串 s1 的长度。 |
4 | strcmp(s1, s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回值小于 0;如果 s1>s2 则返回值大于 0。 |
5 | strchr(s1, ch); 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。 |
6 | strstr(s1, s2); 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。 |
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
char str1[11] = "Hello";
char str2[11] = "World";
char str3[11];
char ch='o';
char str4[] = "orl";
int len ;
//! 复制 str1 到 str3
strcpy( str3, str1);
qDebug("strcpy( str3, str1) : %s",str3);
//! 连接 str1 和 str2
strcat( str1, str2);
qDebug("strcat( str1, str2): %s",str1);
//! 连接后,str1 的总长度
len = strlen(str1);
qDebug("strlen(str1) : %d",len);
//! 查找字符ch
char *pos = strchr(str1,ch);
qDebug("strchr :%d",pos-str1);
//! 查找字符串
pos = strstr(str2,str4);
qDebug("strchr :%d",pos-str2);
//! 字符串比较
int ret = strcmp(str1,str2);
qDebug("strcmp :%d",ret);
return a.exec();
}
输出:
strcpy( str3, str1) : Hello
strcat( str1, str2): HelloWorld
strlen(str1) : 10
strchr :4
strchr :1
strcmp :-1
3.4 指针数组与数组指针
3.4.1 指针数组
指针数组:首先是一个数组,而数组的元素是指针,也就是说,如果数组元素都是相同类型的指针,则称这个数组为指针数组。所谓相同类型的指针是说指针所指向的对象类型是相同的。指针数组是数组元素为指针的数组,其本质为数组。
定义形式:int *p【10】
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! 指针数组
int ix=0;
int array[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int *p[3];
for(ix;ix<3;ix++) p[ix]=array[ix];
for(int i = 0;i<3;i++)
{
for(int j=0;j<4;j++)//注意这里的j要赋值等于0,要不然只能输出第一行1234,达不到预期的效果
{
qDebug("%d",p[i][j]); //或者 *(*(p+i)+j) 或者 *(p[i]+j)
}
}
}
return a.exec();
}
3.4.2 数组指针
数组指针是指向数组首元素的地址的指针,其本质为指针(这个指针存放的是数组首地址的地址,相当于2级指针,这个指针不可移动);
定义方法:(*指针变量名)[长度]即(*P)[n]
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! 数组指针
int array[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int (*p)[4];
//p=(int(*)[4])array;
p =array;
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++) {
qDebug("%d",p[i][j]); //或者 *(*(p+i)+j) 或者 *(p[i]+j)
}
}
return a.exec();
}
3.4.3 二者区别
1) 定义形式:
指针数组:int *p【10】
数组指针:int (*p)【10】
“[]”的优先级比“*”要高。p1 先与“[]”结合,构成一个数组的定义,数组名为p1,int *修饰的是数组的内容,即数组的每个元素。那现在我们清楚,这是一个数组,其包含10 个指向int 类型数据的指针,即指针数组。至于p2 就更好理解了,在这里“()”的优先级比“[]”高,“*”号和p2 构成一个指针的定义,指针变量名为p2,int 修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚p2 是一个指针,它指向一个包含10 个int 类型数据的数组,即数组指针。我们可以借助下面的图加深理解:
2) 所占存储空间的区别
数组指针只是一个指针变量,是C 语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间.
3)应用上的区别
指针数组一般用于处理二维数组。指向一维数组的指针变量用于处理二维数组也是非常方便的。
数组指针和指针数组在处理同一个二维数组时,数组指针的元素个数和指针数组的数组长度不相同,数组指针的元素个数和二维数组的列长度相同。 而指针数组的数组长度和二维数组的行长度相同。
在处理字符串的问题上,使用指针数组处理就比使用数组指针方便多了。因为多个字符串比用二维字符数组处理字符串更加方便,更加的节省内存空间。
相比于比二维字符数组,指针数组有明显的优点:一是指针数组中每个元素所指的字符串不必限制在相同的字符长度;二是访问指针数组中的一个元素是用指针间接进行的,效率比下标方式要高。 但是二维字符数组却可以通过下标很方便的修改某一元素的值,而指针数组却无法这么做。
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int i;
const char *string[3] = {"Mei","Zuo","Chuan"};
const char* p;
if (strcmp(string[0],string[1]) > 0){
p = string[0];
string[0] = string[1];
string[1] = p;
}
if (strcmp(string[0],string[2]) > 0){
p = string[0];
string[0] = string[2];
string[2] = p;
}
if (strcmp(string[1],string[2]) > 0){
p = string[1];
string[1] = string[2];
string[2] = p;
}
for(i=0;i<3;i++){
qDebug("%s, ",string[i]);
}
return a.exec();
}
4. 指针与函数
4.1 指针作为函数参数
#include <QCoreApplication>
void sub(int *px,int *py){
qDebug("sub:%d",*px-*py);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int x = 20,y = 10;
sub(&x,&y);
return a.exec();
}
用指针(地址)作为函数参数,可以“实现通过被调用的函数改变主函数中变量的值”的目的。
4.2 数组指针作为函数参数
实参 | 形参 |
数组名 | 数组名 |
数组名 | 指针变量 |
指针变量 | 数组名 |
指针变量 | 指针变量 |
#include <QCoreApplication>
int arr_add(int arr[],int n){
int sum = 0;
for (int i = 0; i < n; i++){
sum = sum+arr[i];
}
return sum;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int *p,total;
p = array[0];
total = arr_add(p,12);
qDebug("%d",total);
return a.exec();
}
输出:total=78
数组名代表数组的起始地址,用数组名作为参数传递的是地址(将数组起始地址传给被调用函数的形参),既然地址可以作为参数传递,那么指向数组的指针变量也可以作为函数参数。
#include <QCoreApplication>
int arr_add(int *arr,int n){
int sum = 0;
for (int i = 0; i < n; i++){
sum = sum+*(arr+i);
}
return sum;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int *p,total;
p = array[0];
total = arr_add(p,12);
qDebug("%d",total);
return a.exec();
}
4.3 指向函数的指针(函数指针)
一个函数包括一系列的质量,在内存中占据一片存储单元,它有一个起始地址,即函数的入口地址,通过这个地址可以找到该函数,这个地址就称为函数的指针
函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。
定义:类型标识符 (*指针变量名)(形参列表)
int (*p)(),它表示p指向一个返回整型值的函数,注意*p两侧的括弧不能省略,如果写成int *p()就成了返回指针值的函数。
#include <QCoreApplication>
int arr_add(int *arr,int n){
int sum = 0;
for (int i = 0; i < n; i++){
sum = sum+*(arr+i);
}
return sum;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int *p,total;
p = array[0];
int (*pt)(int *arr,int n);
pt = arr_add;
total = (*pt)(p,12);
qDebug("%d",total);
return a.exec();
}
注意:在用指针变量调用函数之前,应先将函数入口地址赋给指针变量。
4.4 指针函数
指针函数是一个函数。函数都有返回类型(如果不返回值,则为无值型),只不过指针函数返回类型是某一类型的指针。
类型名 *函数名(函数参数列表);
#include <QCoreApplication>
int* arr_add(int *arr,int n){
static int sum = 0;
int *point;
point = ∑
for (int i = 0; i < n; i++){
sum += *(arr+i);
}
return (int *)point;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
//float arr_add(),arr_avr();
int *p;
p = array[0];
int* (*pt)(int *arr,int n);
pt = arr_add;
int *total = (*pt)(p,12);
return a.exec();
}
输出:
78
如果static去掉,这样是不对的。因为sum是个局部变量,返回的是sum的地址的副本。而该函数在结束时会回收sum,sum地址指向的值会被后续的别的函数分配和更改。如果使用该指针指向的值会是不确定的。因此才有“永远不要从函数中返回局部自动变量的地址“。
4.5 main函数的参数
main(int argc,char *argv[]),第一个形参argc是个整型变量,第二个形参argv是一个指针数组,其元素指向字符型数据。
int main(int argc,char *argv[]){
while(argc > 1){
++argv;
printf("%s",*argv);
--argc;
}
}
如果从键盘输入的命令:cfile cmputer C_Language
则输出:
computer
C_Language
5. 指针小结
定义形式 | 含义 |
int *p; | p指向整型数据的指针变量 |
int (*p)[n] | p为指向含有n个元素的一维数组的指针变量,数组指针 |
int(*p)() | p为指向函数的指针,该函数返回一个整型值,函数指针 |
int *p[n] | 定义指针数组,它含有n个元素,每个元素指向一个整形数据,指针数组 |
int *p() | p为带回一个指针的函数,该指针指向整型数据,指针函数 |
int **p | p是一个指针变量,它指向一个指向整型数据的指针变量,即指向指针变量的指针,二级指针 |
int (**p)[n] | p是一个指向另一个指针变量的指针变量,被指向的指针变量指向一个含有n个整型数据的一维数组 |