数组与指针
- 数组名数组第一个元素的地址
int ar[10];
int* p = ar;
p == &ar[0];
*p == ar[0];
- 多维数组可看做一维数组,其每个元素也是一个数组
int ar[4][5];
int (*p)[5] = ar;
int* r = ar[0];
p == &ar[0];
*p == ar[0];
r == *p;
r == &ar[0][0];
*r == **p == ar[0][0];
- 使用数组表示法
ar[i]
或ar[i][j]
和使用指针表示法*(ar+i)
或*((ar+i)+j)
两种方法等价。- 但是只有当
ar
是指针变量时, 才能使用ar++
这样的表达式。
- 但是只有当
#include<stdio.h>
int main(void)
{
int ar[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
// 数组表示法
printf("ar[2][1] = %d\n",ar[2][1]);
// 指针表示法
printf("*(*(ar + 2)+1) = %d\n", *(*(ar + 2) + 1));
// 两者混用
printf("*(ar[2]+1) = %d\n", *(ar[2] + 1));
printf("(*(ar+2))[1] = %d\n", (* (ar + 2))[1]);
}
输出:
- 数组元素的存储方式是顺序存储,即相邻元素的存储地址也是相邻的。
#include<stdio.h>
int main(void)
{
int ar[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
// 指向含四个数组的元素的指针
printf("ar = %p\n", ar);
// +1 移动 4*sizeof(int) = 16 个字节
printf("ar + 1 = %p\n", ar +1 );
// 指向 int 类型的指针
printf("*ar = %p\n", *ar);
// +1 移动 1*sizeof(int) = 4 个字节
printf("*ar + 1 = %p\n", *ar + 1);
// 基于顺序存储的特性来遍历数组元素:
int* p = *ar;// p = &ar[0][0]
int rows = 3;
int cols = 4;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
printf("%d\t", *(p + i * cols + j));
}
printf("\n");
}
}
输出:
数组与函数
一维数组与函数
函数要处理一维数组一般有两种方式:
- 数组首元素的地址或指针,和数组的长度作为函数的参数
- 要处理的数组元素的起始指针和终止指针作为函数参数,终止指针一般指向要处理的最后一个数组元素的下一个位置。
/// 第一种方法
/// @param ar 数组名、数组首地址、或指向数组第一个元素的指针
/// 数组长度
void somefunction(int ar[], int len);
void somefunction(int* ar, int len);
// 这里 [] 表示参数类型为指向 int 类型的指针,等价于 int*
// 但只在在声明形式参数时是等价的。
void somefunction(int [],int);
void somefunction(int* ,int);
void somefunction(int ar[], int len)
{
for(int i; i < len; i++)
{
printf("%d\t",ar[i]);
}
}
/// 第二种方法
/// @param begin 指向起始元素的指针
/// @param end 指向最后一个元素的后一个元素
void somefunction(int* begin, int* end);
void somefunction(int*, int*);
// 这里 [] 表示参数类型为指向 int 类型的指针,等价于 int*
// 但只在在声明形式参数时是等价的。
void somefunction(int[], int[]);
void somefunction(int* begin, int* end)
{
int *p;
while(p < end)
{
printf("%d\t",*(p++));
}
}
多维数组与函数
函数处理多维数组的方式与一维数组类似,多维数组可看做一维数组,其每个元素也是一个数组。
/// 对于一维数组
int ar[6];
int* p = ar;// 类型为 int*,+1移动一个 sizeof(int)
/// 对于二维数组
int ar2d[3][4];
int (*p)[4] = ar;// 类型为 int(*)[4],+1移动一个sizeof(int[4])= 4*sizeof(int)
因此,对于多维数组,也可以用传递一个指针和一个长度的方法,指针指向数组的首元素,等于数组名,对于二维数组,长度即是二维数组的行数。
局限性:由于一个有效的指针必须知道其指向的对象的大小,因此,对于多维数组,在其形参声明中必须指定数组除第一个维度外其他维度的大小。对于二维数组来说,必须指明二维数组的列数,因此,用这种方法,函数只能处理列数固定的二维数组,要想处理其他列数的二维数组,必须再写一个函数。
void somefunction(int (*ar)[4],int rows);
void somefunction(int (*)[4],int );
void somefunction(int (*ar)[4],int rows)
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < 4; j++)
{
printf("%d\t",ar[i][j]);
}
printf("\n");
}
}
如何处理任意大小的二维数组 ?
c 的方法
1. VLA
C99 新增的变长度数组(variable-length array, VLA),允许使用变量表示数组的维数。
注意:变长数组不能改变大小,这里的“变”指的是: 在创建数组时, 可以使用变量指定数组的维度。
int sum2d(int rows, int cols, int ar[rows][cols]);
/// 求二维数组所有元素之和的函数
/// @param rows 数组行数
/// @param cols 数组列数
/// @param ar 变长度数组,其尺寸由变量 rows 和 cols 定义
/// @return 返回二维数组所有元素之和
int sum2d(int rows, int cols, int ar[rows][cols])
{
int r;
int c;
int tot = 0;
for (r = 0; r < rows; r++)
for (c = 0; c < cols; c++)
tot += ar[r][c];
return tot;
}
前两个形参(rows
和 cols
) 用作第 3 个形参二维数组 ar
的两个维度。因为 ar
的声明要使用 rows
和 cols
, 所以在形参列表中必须在声明 ar
之前先声明这两个形参。
2. 基于顺序存储的特性
数组元素的存储方式是顺序存储,即相邻元素的存储地址也是相邻的,对于二维数组,它的相邻每行的存储地址都是相邻的,而每行又是顺序存储的,所以,相邻每行首尾相连可以看做一个大的一维数组,只需要知道这个一维数组第一个数据元素的地址 int* ar
即可确定任意位置的元素,如第 i 行第 j 列的元素为:*(ar+i*cols+j)
int sum2d(int rows, int cols, int* ar);
/// 求二维数组所有元素之和的函数
/// @param rows 数组行数
/// @param cols 数组列数
/// @param ar 二维数组第一个元素的地址
/// @return 返回二维数组所有元素之和
int sum2d(int rows, int cols, int* ar)
{
int r;
int c;
int tot = 0;
for (r = 0; r < rows; r++)
for (c = 0; c < cols; c++)
tot += ar[r*cols+c];
return tot;
}
3. 使用指针数组
创建一个指针数组,让其每个元素都是指向二维数组每行的首元素。
int sum2d(int rows, int cols, int* ar[]);
/// 求二维数组所有元素之和的函数
/// @param rows 数组行数
/// @param cols 数组列数
/// @param ar 指针数组,其每个元素都是一个指针,指向二维数组每行的首元素
/// @return 返回二维数组所有元素之和
int sum2d(int rows, int cols, int* ar[])
{
int r;
int c;
int tot = 0;
for (r = 0; r < rows; r++)
for (c = 0; c < cols; c++)
tot += ar[r][c];
return tot;
}
C++ 的方法
使用 vector
- 二维数组的声明方式:
// 使用初始化列表
// vector<vector<int>> 中每个元素都是 vector<int> ,表示二维数组的每行。
vector<vector<int>> arr1{ {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13,14,15,16} };
// 使用 push_back();
vector<vector<int>> arr2;
for (int i = 0; i < 4; i++)
{
vector<int> temp{ i*4 + 1, i*4 + 2, i*4 + 3, i*4 + 4 };
arr2.push_back(temp);
}
int sum2d(vector<vector<int>> arr)
{
int tot = 0;
for (auto& e : arr)
for (auto& c : e)
tot += c;
return tot;
}
标签:rows,int,元素,cols,C++,ar,数组,指针
From: https://www.cnblogs.com/Critical-Thinking/p/16862714.html