需求:通過封裝的函數使指針 q的指向改變(以前指向a,現在要指向b)
說的明白點:主函數中有個指針 int *q=&a; 把指針q作為參數傳入自己寫的函數
- int a=10,b=100;
- int *q=&a;
- void func(怎么寫q)
- {
- 怎么寫
- }
通過函數實現q=&b
錯誤案例1:
#include<iostream>
using namespace std;
int a= 10;
int b = 100;
int *q;
void func(int *p)
{
p = &b;
}
int main()
{
q = &a;
func(q);
system("pause");
return 0;
}
分析:雖然我們是用指針傳值,但是並不能改變參數的本質:p只是q的副本,副本p怎么變也變不了q的值。
錯誤案例2:
#include<iostream>
using namespace std;
int a= 10;
int b = 100;
int *q;
void func(int *p)
{
*p = b; //把p=&b 改
}
int main()
{
q = &a;
func(q);
cout<<a<<endl;
system("pause");
return 0;
}
分析:*p=*q=*(&a)=a 也就是p的值對應地址的值改為100.所以外部a=100,但q的值不會變。
因為*p只是修改a地址的內容。
雖然p是q的副本(假如q=FF01,則p也=FF01),但是我們通過解引用直接修改了a的內存,使外部的a變了。
上例雖然錯誤,但我們得出
結論:通過解引用我們直接修改內存數據,則不論函數內部、外部、是不是副本,只要變量名、指針、引用與這塊內存地址有關,全都改變。

從上圖我們得到:對一級指針的解引用賦值就是對它下級的數據的修改,同理,二級的解引用就是對一級的數據的直接修改。
我們再看題目 一級指針q=&a 要變為q=&b 也就是要把q的數據(FF01,中間那個)換為&b
怎么換?就是通過它的上級指針(q1)的解引用賦值 即*q1=&b, q1是一個二級指針。
所以我們知道函數內部
void func(/*因為q1是二級指針,所以參數也就要二級指針接收*/int**q1)
{
*q1 =&b;
}
正確代碼1:
#include<iostream>
using namespace std;
int a= 10;
int b = 100;
int *q;
void func(int **p) //2
{
cout<<"func:&p="<<&p<<",p="<<p<<endl;
*p = &b; //3
cout<<"func:&p="<<&p<<",p="<<p<<endl;
}
int main()
{
cout<<"&a="<<&a<<",&b="<<&b<<",&q="<<&q<<endl;
q = &a;
cout<<"*q="<<*q<<",q="<<q<<",&q="<<&q<<endl;
//下面2行可以換為一行 func(&q);
//**************************
int **q1=&q;
func(q1);
//*******************
//func(&q);
cout<<"*q="<<*q<<",q="<<q<<",&q="<<&q<<endl;
system("pause");
return 0;
}
其實在c++中還有一種方法就是用
指針的引用
#include<iostream>
using namespace std;
int a= 10;
int b = 100;
int *q;
void func(int *&p) //p就是q的別名 q是一級指針 所以參數要是int*
{
p = &b; //改變p就是改變q
}
int main()
{
q = &a;
func(q);
system("pause");
return 0;
}
二、二級指針實際中的應用
需求:封裝一個函數 從堆區 給str申請一個空間 並賦值為"hello world"
也就是在封裝的函數中在堆區申請空間,用函數外的指針維護申請的空間
#include<iostream>
using namespace std;
void my_str2(char**my_str)
{
*my_str = new char[15];
strcpy(*my_str, "hello world");
}
int main()
{
char *str = NULL;
my_str2(&str);
cout<<"str = "<<str<<endl;
delete[] str;
str=NULL;
system("pause");
return 0;
}
當然也可以用指針的引用
#include<iostream>
using namespace std;
void my_str2(char*&my_str)
{
my_str = new char[15];
strcpy(my_str, "hello world");
}
int main()
{
char *str = NULL;
my_str2(str);
cout<<"str = "<<str<<endl;
delete[] str;
str=NULL;
system("pause");
return 0;
}
1、傳參規則
- 當二級指針作為函數形參時,能作為函數實參的是二級指針,指針數組,一級指針的地址
- 當數組指針作為函數形參時,能作為函數實參的是二維數組,數組指針
- 當二維數組作為函數形參時,能作為函數實參的是二維數組,數組指針
- 當指針數組作為函數形參時,能作為函數實參的是指針數組,二級指針,一級指針的地址
2、實例驗證:
#include <stdio.h>
#include <stdlib.h>
void fun1(int **pp)
{
printf("fun1\n");
}
void fun2(int(*a_p)[5])
{
printf("fun2\n");
}
void fun3(int t_d_a[][5])
{
printf("fun3\n");
}
void fun4(int *p_a[5])
{
printf("fun4\n");
}
int main()
{
int *p_a[5]; //指針數組
int **pp = NULL; //二級指針
int *p = NULL; //一級指針
int t_d_a[5][5]; //二維數組
int a[5]; //一維數組
int(*a_p)[5] = &a; //數組指針
fun1(p_a);
fun1(pp);
fun1(&p);
//fun1(t_d_a);
//fun1(a_p);
printf("\n");
//fun2(p_a);
//fun2(pp);
//fun2(&p);
fun2(t_d_a);
fun2(a_p);
printf("\n");
//fun3(p_a);
//fun3(pp);
//fun3(&p);
fun3(t_d_a);
fun3(a_p);
printf("\n");
fun4(p_a);
fun4(pp);
fun4(&p);
//fun4(t_d_a);
//fun4(a_p);
printf("\n");
return 0;
}
