首页 > 编程语言 >C/C++ 数组、指针与函数

C/C++ 数组、指针与函数

时间:2022-11-06 15:45:26浏览次数:63  
标签:rows int 元素 cols C++ ar 数组 指针

数组与指针

  • 数组名数组第一个元素的地址
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;
}

前两个形参(rowscols ) 用作第 3 个形参二维数组 ar 的两个维度。因为 ar 的声明要使用 rowscols, 所以在形参列表中必须在声明 ar 之前先声明这两个形参。

(13 封私信 / 80 条消息) 哪些C语言编译器支持VLA(变长数组)? - 知乎 (zhihu.com)

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

相关文章

  • 实验四 类与数组、指针
    实验任务五代码截图:  vectorInt.hpp:1#pragmaonce23#include<iostream>4#include<cassert>5usingnamespacestd;67classvectorInt8{9p......
  • C++图书馆管理系统
    C++图书馆管理系统程序设计题六:图书馆管理系统1问题描述该系统要求建立一个图书馆管理系统,并具有排序、查找、计算、显示等功能。通过此课题,熟练掌握文件、数组、指针......
  • C/C++中的枚举数据类型
    关键字:Emum自定义名称{a=1b=2,c=3,d=4}box;定义好之后可以直接通过box关键字调用ennumbag{book1="百年孤独",book2="时间简史",book3="简爱"}boo......
  • C/C++表达式求值(带括号)
    C/C++表达式求值(带括号)实验内容及要求(功能)1.友好的用户界面,给出简单用户帮助2.通过键盘输入表达式(负数,小数),表达式可包含加(+)、减(-)、乘(*)、除(/)、求模(%)、开......
  • C++ Balanced Braces
    C++BalancedBracesAstringofcharactershasbalancedbraces(parentheses,curlybraces,andsquarebraces)ifeachright-facingbraceoccurringinthestrin......
  • [哈希]leetcode349. 两个数组的交集
    题目给定两个数组 nums1 和 nums2,返回它们的交集 。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序。示例1:输入:nums1=[1,2,2,1],nums2......
  • Effective C++ - 条款17 - 总是以独立语句将new对象放入到智能指针中
    这个条款所说的意思就是,不要把new对象并放入智能指针这个操作放入到一个别的过程之中。例如,如果把new对象并放入智能指针放入到一个传参过程之中,可能会发生其他参数的执行......
  • Effective C++ - 条款16 - new和delete使用相同的形式
    不要对数组做typedef,会产生很多问题,尽量使用std的string和vector来代替。new和new一个数组时,内存实际布局有区别,new数组时,会在开头记录数组长度(具体编译器有不同实现,但......
  • 一些简单的指针操作(day3)
    1.认识指针的一些基本性质通过下面几段代码理解指针操作指定变量的一些基础性质。实例#include<stdio.h>intmain(){inta=2;int*p=&a; printf("%d\n",a); print......
  • 解决Dev-C++中文注释无法显示,单击才能显示的问题
    解决Dev-C++中文注释无法显示,单击才能显示的问题_任青月的博客-CSDN博客......