多级指针
#include <iostream>
using namespace std;
int main() {
int block1 = 888;
int *block2 = &block1;
int** block3 = &block2;
int*** block4 = &block3;
int**** block5 = &block4;
cout << "block2:" << *block2 << endl;
cout << "block3:" << **block3 << endl;
cout << "block4:" << ***block4 << endl;
cout << "block5:" << ****block5 << endl;
return 0;
}
指针表示法和数组表示法
我们可以用数组或者指针来访问数组
int main() {
int months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int len = sizeof(months) / sizeof(months[0]);
for (int i = 0; i < len; i++) {
//数组表示法
cout << "months[" << i << "] = " << months[i] << endl;
//指针表示法
int* p = months;
cout << "*(p + " << i << ") = " << *(p + i) << endl;
}
return 0;
}
练习一
我们需要完成一个需求,寻找二维数组中第一大的数字和第二大的数字。
1.记得处理边界情况 如果数组元素<=1 则不合法
2.设置两个变量,第一个变量是记录最大的值first , 第二个变量是记录次大的值second
输入总行数 总列数
将数据输入到二维数组里面
然后处理<=1 的情况
比较nums[0][0] 和nums[0][1] 的值 赋值给first 和 second
然后for(int i = 0 ; i < m *n ; i ++ ){
如果second >= nums[i / (n)][i % (n)] 跳过
如果second < nums[i / n][i % n]; && nums[i / n][i % n] <= first
second = nums[i] / n[i % n];
如果first < nums[i / n][i % n]
second = first;
first = nums[i / n][i % n];
}
#include <iostream>
using namespace std;
#define MAX_SIZE 128
int arr[MAX_SIZE][MAX_SIZE];
int main() {
int m, n;
cin >> m >> n;
int firstValue , secondValue;
if (m < 0 || n < 0 || m * n <= 1) {
cout << "Invalid input" << endl;
return 0;
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
cin >> arr[i][j];
if (arr[0][0] > arr[0][1]) {
firstValue = arr[0][0];
secondValue = arr[0][1];
}else{
firstValue = arr[0][1];
secondValue = arr[0][0];
}
for (int i = 2; i < m * n; i++) {
if (secondValue >= arr[i / n][i % n]) continue;
if (firstValue < arr[i / n][i % n]) {
secondValue = firstValue;
firstValue = arr[i / n][i % n];
}else{
secondValue = arr[i / n][i % n];
}
}
cout << "The second largest value is: " << secondValue << endl;
cout << "The largest value is: " << firstValue << endl;
return 0;
}
使用指针的方法
#include <iostream>
using namespace std;
#define MAX_SIZE 128
int arr[MAX_SIZE][MAX_SIZE];
int main() {
int m, n;
cin >> m >> n;
int *firstValue , *secondValue;
if (m < 0 || n < 0 || m * n <= 1) {
cout << "Invalid input" << endl;
return 0;
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
cin >> arr[i][j];
if (arr[0][0] > arr[0][1]) {
*firstValue = arr[0][0];
*secondValue = arr[0][1];
}else{
*firstValue = arr[0][1];
*secondValue = arr[0][0];
}
for (int i = 2; i < m * n; i++) {
if (*secondValue >= arr[i / n][i % n]) continue;
if (*firstValue < arr[i / n][i % n]) {
*secondValue = *firstValue;
*firstValue = arr[i / n][i % n];
}else{
*secondValue = arr[i / n][i % n];
}
}
cout << "The second largest value is: " << secondValue << endl;
cout << "The largest value is: " << firstValue << endl;
return 0;
}
我们如何用指针数组的方式遍历数组
第一种方式:
int A[4][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
int (*p)[3] = &A[0]; // 定义一个指向三个成员的数组的指针
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++)
cout << (*p)[j] << " ";
cout << endl;
p++; // 指向下一个数组
}
第二种方式:
int A[4][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
int* p = NULL;
for (int i = 0; i < 4; i++) {
p = A[i];
for(int j = 0 ; j < 3 ; j ++ )
cout << *(p + j) << " ";
cout << endl;
}
练习二
找二维数组里值最小的数
#include <iostream>
using namespace std;
int main() {
int A[4][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
int (*p)[3] = &A[0];
int* boy = &(*p)[0];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++)
if (*boy > *((*p) + j)) {
boy = &(*p)[j];
}
p++;
}
cout << *boy << endl;
return 0;
}
数组与指针的区别
数组:数组是用于储存多个相同类型数据的集合。
指针:指针是一个变量,但是它和普通变量不一样,它存放的是其它变量在内存中的地址。
1.赋值
数组:只能一个一个元素的赋值或拷贝
指针:指针变量可以相互赋值
2.表示范围
数组有效范围就是其空间的范围,数组名使用下表引用元素,不能指向别的数组
指针可以指向任何地址,但是不能随意访问,必须依附在变量有效范围之内
3. sizeof数组:
数组所占存储空问的内存:sizeof(数组名)
数组的大小:sizeof(数组名)/sizeof(数据类型)
指针:
在 32位平台下,无论指针的类型是什么,sizeof(指针名)都是4.
在64位平台下,无论指针的类型是什么,sizeof(指针名)都是8.
指针数组和数组指针
指针数组:
int *ptr[2]; // 定义一个两个元素的数组 数组元素是指针变量
int salary1 = 1 , salary2 = 2;
ptr[0] = &salary1;
ptr[1] = &salary2;
数组指针:
int (*p)[3]; //定义了一个指向三个成员的数组的指针
访问元素的两个方式
int A[4][3] = { {省略}};
数组表示法:(*p)[j];
指针表示法:*((*p) + j)
传参
数组传参时,会退化为指针!
(1)退化的意义:C语言只会以值拷贝的方式传递参数,参数传递时,如果只拷贝整个数组,效率会大大降低,并且在参数位于栈上,太大的数组拷贝将会导致溢出。
(2)因此C语言将数组的传参进行了退化。将整个数组拷贝一份传入函数时,将数组名看做常量指针,传数组首元素的地址。
我们还可以使用指针数组访问数组元素
#include <iostream>
using namespace std;
void method(int* arr[], int size) {
for(int i = 0 ; i < size ; i ++ )
cout << *(arr[i]) << " ";
cout << endl;
}
int main() {
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int* arrPtr[10] = { 0 };
for (int i = 0; i < 10; i++) {
arrPtr[i] = &arr[i];
}
method(arrPtr, 10);
return 0;
}
使用指针数组来进行访问
*(arr + i) 解引用 是一个指针 然后再解引用*得到值
#include <iostream>
using namespace std;
void method(int** arr, int size) {
for (int i = 0; i < size; i++)
cout << *(*(arr + i)) << " ";
}
int main() {
int arr[5] = { 1, 2, 3, 4, 5 };
int* arrPtr[5] = { 0 };
for (int i = 0; i < 5; i++)
arrPtr[i] = &arr[i];
method(arrPtr, 5);
return 0;
}
二维数组的访问方式
利用指针数组 new方式
#include <iostream>
using namespace std;
void processArray(int** arr, int rows, int cols) {
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
cout << "arr[" << i << "][" << j << "] = " << arr[i][j] << endl;
}
}
}
int main() {
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 创建一个指向每一行的指针数组
int** ptrArr = new int* [3];
for (int i = 0; i < 3; ++i) {
ptrArr[i] = arr[i]; // 每个ptrArr[i]指向arr[i]
}
processArray(ptrArr, 3, 4); // 传递指针数组到函数
delete[] ptrArr; // 释放动态分配的内存
return 0;
}
指针相加减
(1) 使用“指针-指针”的方式计算整数数组元素的偏移值
(2) 使用“指针-指针”的方式计算字符串元素的偏移值
int ages[] = {20, 25, 30, 35, 40};
int len = sizeof(ages) / sizeof(ages[0]);
int* martin = ages + 1;
int* john = ages + 2;
cout << "martin address:" << martin << " " << *martin << endl;
cout << "john address:" << john << " " << *john << endl;
cout << "martin - john:" << john - martin << endl;
指针-指针是直接计算偏移值 不是计算相差字节数
但是不允许指针相加,只允许+一个常量 或者 一个枚举常量
知识点:
(1)指针和指针可以做减法操作,但不适合做加法运算;
(2)指针和指针做减法适用的场合:两个指针都指向同一个数组,相减结果为两个指针之间的元素数目,而不是两个指针之间相差的字节数。
比如:intint array[4]={12,34, 56, 78};
int *p int1= &int array[0];
int *p int2 = &int array[3];
p_int2-p_int1 的结果为 3,即是两个之间之间的元素数目为3个。
如果两个指针不是指向同一个数组,它们相减就没有意义。
(3)不同类型的指针不允许相减,比如
char *pl;
imnt *p2;
p2-p1是没有意义的。