指针数组的本质是数组,只是每个数组的元素为指针
32位平台:
char*arr1[4];
int *arr2[4];
short *arr3[4];sizeof(arr1)==168;
sizeof(arr2)==168;
sizeof(arr3)==168;
8.4.1 数值的指针数组
int *arr[4]; 指针数组
int *arr[4]={&num1,&num2,&num3,&num4};
int num1=10;
int num2=20;
int num3=30;
int num4=40;
//int arr[4]
//int *p;
int *arr[4]={&num1.&num2,&num3,&num4};
int n=sizeof(arr)/sizeof(arr[0]);
int i;
//遍历输出
for(int i=0;i<n;i++){
cout<<arr[i]<<" "; //10 20 30 40
}
cout<<endl;
8.4.2 字符指针数组
char*arr[4]={"hehehehe","xixixixi","lalalala","hahahaha"};
arr[0]存放的是hehehehe的首元素地址,存放在栈区/全局区(看这个数组是全局还是局部),同时,"hehehehe"被存放在文字长量区。注意:文字长量区的值不可被修改
char*arr[4]={"hehehehe","xixixixi","lalalala","hahahaha"};
int n=sizeof(arr)/sizeof(arr[0]);
int i;
for(i=0;i<n;i++){
cout<<arr[i]<<endl; //这里输出不需要加*号,arr[i]它保存的就是字符串首元素地址,输出结果为 hehehehexixixixilalalala hahahaha}
// cout<<*arr[i]; 输出的就是第0个元素内容,就是 h,x,l,h;// cout<<*(arr[i]+3)<<endl; 这里输出的是字符串第三个元素,e,i,a,a
8.4.3 二维字符数组
char*arr1[4]={"hehehehe","xixixixi","lalalala","hahahaha"};
char arr2[4][128]={"hehehehe","xixixixi","lalalala","hahahaha"};
arr1是在指针数组 存放的是每个字符串的首元素地址
arr2是二维数组 存放的是每个字符串
8.5 指针的指针
int num=10;
int *p=#
int **q=&p;
如果想要保存p的地址,则需要两个*号
n级变量可以保存n-1级指针变量的地址
8.6数组指针
int arr[5]={10,20,30,40,50};
int (*p)[5];//数组指针,注意()不能去掉,去掉就和5结合
#include<iostream>
using namespace std;
void test1() {int arr[5] = { 10,20,30,40,50 };int(*p)[5] = &arr;//数组指针cout << "sizeof(p)=" << sizeof(p) << endl;cout << "p=" << p << endl;cout << "p+1=" << p + 1;
}int main() {test1();return 0;}
int arr[5]={10,20,30,40,50};
int(*P)[5]=&arr; //数组指针
*p==*&arr==arr;*和&抵消
对数组首地址取*==数组首元素地址
注意:若想取arr[2]内容,必须*(*p+2)=*(*(p+0)+2)==*(p[0]+2)==p[0][2]
8.6.2二维数组和数组指针的关系
int arr[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
arr[0] (值为1,2,3,4) |
arr[1] (5,6,7,8) |
arr[2] (9,10,11,12) |
arr[1]=>*(arr+1) //第1行第0列的列地址
&arr[1]=>arr+1 //第1行的行地址
*arr+1=>//第0行第1列的列地址
arr[1]+2=>*(arr+1)+2=>//第1行第2列的列地址
#include<iostream>
using namespace std;
int main() {int arr[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };int row = sizeof(arr) / sizeof(arr[0]); //行为3int col = sizeof(arr[0]) / sizeof(arr[0][0]);//列为4int* p = &arr[0][0];int i = 0;for (int i = 0; i < row * col; i++) { //依次输出arr[i]cout << p[i] << " ";}return 0;
}
8.8 指针与函数
8.8.1 指针变量作为函数的参数
如果想在函数内部 修改外部变量的值 需要将外部变量的地址 传递给函数(重要)
案列1 单向传递之值传递
函数内部 不能修改外部变量的值
#include<iostream>
using namespace std;
void setNum01(int data)
{
data=100;
}
void test1(){
int num=0;
setNum01(num);//单向传递之 传值
cout<<"num="<<num<<endl; //输出结果为0.修改不成功
}
int main(int argc,char*argv[])
{
test1();
return 0;
}
案例2 单向传递之传地址
函数内部就可以修改外部变量的值
void setNum02(int *p)//int *p=#
{
*p=100;
}
void test2(){int num=0;
setNum02(&num);//单向传递之传地址
cout<<"num="<<num<<endl; //结果为100
}
8.8.2 一维数组作为函数的参数
函数内部想操作(读或写)外部数组元素,将数组名传递给函数
注意:一维数组 作为函数的形参 会被优化成指针变(面试中常用)
//void outIntArray(int arr[5], int n) {
// 注意:一维数组作为函数的参数 会被编译器 优化成 指针变量void outIntArray(int *arr, int n) {cout << "内部sizeof(arr)=" << sizeof(arr) << endl; for (int i = 0; i < n; i++) {cout << arr[i] << " ";}
}
void test02() {int arr[5] = {10,20,30,40,50};int n = sizeof(arr) / sizeof(arr[0]);cout << "外部sizeof(arr)=" << sizeof(arr) << endl; //20B//遍历数组:outIntArray(arr,n);// 10 20 30 40 50
}int main() {test02();return 0;}
8.8.3 二维数组作为函数的参数
函数内部 想操作 函数外部的二维数组 需要将二维数组名 传递给函数
二维数组 作为函数的形参 会被优化成 一维数组
//void outputIntArray(int arr[3][4], int row, int col) {
//二维数组作为函数的形参 会被优化成 一维数组指针void outputIntArray(int ( * arr)[4],int row,int col){cout << "内部sizeof(arr)=" << sizeof(arr) << endl;for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {cout << arr[i][j] << " ";}cout << endl;}
}
void test03() {int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };int row = sizeof(arr) / sizeof(arr[0]);int col = sizeof(arr[0]) / sizeof(arr[0][0]);cout << "外部sizeof(arr)=" << sizeof(arr) << endl;//遍历数组outputIntArray(arr, row, col);}int main() {test03();return 0;}
8.8.4 函数的返回值类型为 指针类型
将函数内部的合法地址 通过返回值 返回给函数外部
int* getAddr(void) {int data = 20;//data在函数内部,是局部变量,在函数被调用之后会被释放//*p就等于在访问一个被释放的空间,这时候就会出现段错,操作非法空间return &data; //不要返回普通局部变量的地址 } void test04() {int* p = NULL;p = getAddr();cout << "p=" << *p;//结果会出现段错,输出不了 }int main() {test04();return 0;}
修改之后为:
int* getAddr(void) {//int data = 20;//data在函数内部,是局部变量,在函数被调用之后会被释放//*p就等于在访问一个被释放的空间,这时候就会出现段错,操作非法空间static int data = 20;//添加局部静态变量staticreturn &data; //不要返回普通局部变量的地址
}
void test04() {int* p = NULL;p = getAddr();cout << "p=" << *p;//20
}int main() {test04();return 0;}
8.9 函数指针
函数名 代表函数的入口地址:
函数指针:本质是一个指针变量 只是改变量 保存的是函数的入口地址
int myAdd(int x, int y) {return x + y;
}
void test05() {int(*p)(int x, int y) = NULL;//函数指针和函数入口地址建立关系p = myAdd;//通过p调用myAdd函数(函数+(实参))cout << p(10, 20); //30
}int main() {test05();return 0;}
8.9.2 函数指针变量注意:
函数指针变量不要+1 无意义
不要对函数指针变量取*
8.9.3 函数指针变量 使用typedef定义
int myAdd(int x, int y) {return x + y;
}
void test05() {typedef int(*FUN_abs)(int x, int y);FUN_abs p = NULL;//函数指针和函数入口地址建立关系p = myAdd;//通过p调用myAdd函数(函数+(实参))cout << p(10, 20); //30
}int main() {test05();return 0;}
8.9.4 函数指针作为函数的参数
目的:让算法功能多样化
案例1:设计一个算法,完成加减乘除
int myAdd(int x, int y) {return x + y;
}
int mysub(int x, int y) {return x - y;
}
int mymul(int x, int y) {return x * y;
}
int mydiv(int x, int y) {return x / y;
}
int choice(int x, int y, int (*func)(int, int)) {return func(x, y);
}
void test07() {cout << choice(20, 30, myAdd) << endl;cout << choice(20, 30, mysub) << endl;cout << choice(20, 30, mymul) << endl;cout << choice(20, 30, mydiv) << endl;
}int main() {test07();return 0;}