C语言 详细讲解数组参数与指针参数

目录
  • 一、C语言中的数组参数退化为指针的意义
  • 二、二维数组参数
  • 三、等价关系
  • 四、被忽视的知识点
  • 五、小结

一、C语言中的数组参数退化为指针的意义

C 语言中只会以值拷贝的方式传递参数

当向函数传递数组时:

  • 将整个数组拷贝一份传入函数        ×
  • 将数组名看做常量指针传数组首元素地址    √

C 语言以高效作为最初设计目标:

  • a) 参数传递的时候如果拷贝整个数组执行效率将大大下降。
  • b) 参数位于栈上,太大的数组拷贝将导致栈溢出。

二、二维数组参数

二维数组参数同样存在退化的问题

  • 二维数组可以看做是一维数组
  • 二维数组中的每个元素是一维数组

二维数组参数中第一维的参数可以省略

void f(int a[5])    <-->    void f(int a[ ])    <-->    void f(int* a)

void g(int a[3][3])    <-->    void g(int a[ ][3])    <-->    void g(int(*a)[3])

三、等价关系

数组参数 等效的指针参数
一维数组:float a[5] 等效的指针参数:float* a
指针数组:int* a[5] 指针的指针:int** a
二维数组:char a[3][4] 数组的指针:char (*a)[4]

四、被忽视的知识点

C 语言中无法向一个函数传递任意的多维数组

必须提供除第一维之外的所有维长度

  • 第一维之外的维度信息用于完成指针运算
  • N 维数组的本质是一维数组,元素是 N-1 维的数组
  • 对于多维数组的函数参数只有第一维是可变的

下面看一个传递与访问二维数组与三维数组的示例:

#include <stdio.h>

void access(int a[][3], int row)
{
    int col = sizeof(*a) / sizeof(int);
    int i = 0;
    int j = 0;

    printf("sizeof(a) = %d\n", sizeof(a));
    printf("sizeof(*a) = %d\n", sizeof(*a));

    for(i=0; i<row; i++)
    {
        for(j=0; j<col; j++)
        {
            printf("%d\n", a[i][j]);
        }
    }

    printf("\n");
}

void access_ex(int b[][2][3], int n)
{
    int i = 0;
    int j = 0;
    int k = 0;

    printf("sizeof(b) = %d\n", sizeof(b));
    printf("sizeof(*b) = %d\n", sizeof(*b));

    for(i = 0; i < n; i++)
    {
        for(j = 0; j < 2; j++)
        {
            for(k = 0; k < 3; k++)
            {
                printf("%d\n", b[i][j][k]);
            }
        }
    }

    printf("\n");
}

int main()
{
    int a[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
    int aa[2][2] = {0};
    int b[1][2][3] = {0};

    access(a, 3);
    //access(aa, 2);
    access_ex(b, 1);
    //access_ex(aa, 2);

    return 0;
}
 

输出结果如下:

五、小结

  • C 语言中只会以值拷贝的方式传递参数
  • C 语言中的数组参数必然退化为指针
  • 多维数组参数必须提供除第一维之外的所有维长度
  • 对于多维数组的函数参数只有第一维是可变的

到此这篇关于C语言 详细讲解数组参数与指针参数的文章就介绍到这了,更多相关C语言 数组参数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言全方位讲解数组的使用

    目录 一维数组的创建和初始化 1.数组的创建 2.数组创建方式 3.数组的初始化 一维数组的使用 一维数组的存储 二维数组的创建与初始化 1.二维数组的创建 2.二维数组的初始化 二维数组的存储 数组的越界 总结 接着上次的操作符的详解,让我们来简单了解C语言里的数组. 一维数组的创建和初始化 1.数组的创建 数组是一组相同类型的元素的集合. 2.数组创建方式 type_t(数组类型) arr_name(数组名) [const_n](用来指定数组大小) 3.数组的初始化 数组的初始化是在其定义的

  • C语言数组超详细讲解上

    目录 前言 1.一维数组的创建和初始化 1.1 一维数组的创建 1.2 一维数组的初始化 1.3 一维数组的使用 1.4 一维数组在内存中的存储 2.二维数组的创建和初始化 2.1 二维数组的创建 2.2 二维数组的初始化 2.3 二维数组的使用 2.4 二维数组在内存中的存储 3.数组越界 4.数组作为函数参数 4.1 冒泡排序函数的错误设计 4.2 数组名是什么? 4.3 对数组名的用法进行总结 4.4 冒泡排序函数的正确设计 总结 前言 本文主要介绍数组相关的内容,主要内容包括: 一维数组

  • C语言数组的各种操作梳理

    目录 一.一维数组 1.创建 2.初始化 3.使用 4.数组在内存中的存储 5.数组大小的计算 二.二维数组 1.创建 2.初始化 3.使用 4.二维数组在内存中的存储 三.数组作为函数参数 1.关于数组名是数组首元素的地址的两个例外 2.冒泡排序 一.一维数组 1.创建 //如何创建数组 int num[10]; char arr[10]; double sum[10]; float fix[10]; //变长数组 //数组的大小是变量 //C99语法支持 int a = 10; int ar

  • C语言 从根本上理解数组

    目录 一.数组的概念 二.数组的大小 三.数组地址与数组名 四.数组名的盲点 五.小结 一.数组的概念 数组是相同类型的变量的有序集合 二.数组的大小 数组在一片连续的内存空间中存储元素 数组元素的个数可以显示或隐式指定 下面看一段数组初始化的代码: #include <stdio.h> int main() { int a[5] = {1, 2}; int b[] = {1, 2}; printf("a[2] = %d\n", a[2]); printf("a[

  • C语言 详细讲解数组参数与指针参数

    目录 一.C语言中的数组参数退化为指针的意义 二.二维数组参数 三.等价关系 四.被忽视的知识点 五.小结 一.C语言中的数组参数退化为指针的意义 C 语言中只会以值拷贝的方式传递参数 当向函数传递数组时: 将整个数组拷贝一份传入函数        × 将数组名看做常量指针传数组首元素地址    √ C 语言以高效作为最初设计目标: a) 参数传递的时候如果拷贝整个数组执行效率将大大下降. b) 参数位于栈上,太大的数组拷贝将导致栈溢出. 二.二维数组参数 二维数组参数同样存在退化的问题 二维数

  • C语言详细讲解多维数组与多维指针

    目录 一.指向指针的指针 二.二维数组与二维指针 三.数组名 四.小结 一.指向指针的指针 指针的本质是变量 指针会占用一定的内存空间 可以定义指针的指针来保存指针变量的地址值 为什么需要指向指针的指针? 指针在本质上也是变量 对于指针也同样存在传值调用与传址调用 下面看一个重置动态空间大小(从 size 到 new_size)的代码: #include <stdio.h> #include <malloc.h> int reset(char** p, int size, int

  • C语言详细讲解指针数组的用法

    目录 1. 指针数组定义方法 2. 指针的指针(二级指针) 3. 字符串和指针 4. 数组指针 定义方法 数组指针的用法 1. 指针数组定义方法 格式: 类型说明符 *数组名[ 元素个数 ] int *p[10]; // 定义了一个整型指针数组p,有10个元素,都是int *类型的变量 指针数组的分类: 同指针类型的分类,见上一篇 大多数情况下,指针数组都用来保存多个字符串. #include <stdio.h> int main() { char *name[5] = {"Hell

  • C语言超详细讲解指向函数的指针

    目录 一.函数的指针 二.指向函数的指针变量 三.调用函数的两种方式 四.指向函数的指针的作用 五.用指向函数的指针作函数参数(重点) 六.为什么要将指向函数的指针变量作为函数的形参(重点) 一.函数的指针 首先,函数名代表函数的起始地址,调用函数时,程序会从函数名获取到函数起始地址,并从该地址起执行函数中的代码,函数名就是函数的指针,所以我们可以定义一个指向函数的指针变量,用来存放函数的起始地址,这样一来,就可以通过该变量来调用其所指向的函数. 二.指向函数的指针变量 定义指向函数的指针变量

  • C++超详细讲解数组操作符的重载

    目录 一.字符串类的兼容性 二.重载数组访问操作符 三.小结 一.字符串类的兼容性 问题:string 类对象还具备 C 方式字符串的灵活性吗?还能直接访问单个字符吗? string 类最大限度的考虑了 C 字符串的兼容性 可以按照使用 C 字符串的方式使用 string 对象 下面看一个用 C 方式使用 string 类的示例: #include <iostream> #include <string> using namespace std; int main() { stri

  • C语言详细讲解常用字符串处理函数

    目录 一.strlen() 1. 函数原型: 2. 手动实现: 二.strcat() 1. 函数原型: 2. 手动实现: 三.strcpy() 1. 函数原型: 2. 手动实现: 四.strcmp() 1. 函数原型: 2. 手动实现: 五.memset() 1. 函数原型: 2. 手动实现: 一.strlen() 1. 函数原型: size_t strlen(const char *str) 参数str: 要计算的字符串的长度返回值: 返回字符串 str 的长度,直到遇到结束字符'\0',但不

  • C语言 详细讲解#pragma的使用方法

    目录 一.#pragma 简介 二.#pragma message 三.#pragma once 四.#pragma pack 五.小结 一.#pragma 简介 #pragma 用于指示编译器完成一些特定的动作 #pragma 所定义的很多指示字是编译器特有的 #pragma 在不同的编译器间是不可移植的 预处理器将忽略它不认识的 #pragma 指令 不同的编译器可能以不同的方式解释同一条 #pragma 指令 一般用法: #pragma parameter 注:不同的 parameter

  • C语言详细讲解二分查找用法

    目录 [力扣题号]704.二分查找 力扣题目链接 示例 1: 输入: nums = [-1,0,3,5,9,12], target = 9     输出: 4       解释: 9 出现在 nums 中并且下标为 4 示例 2: 输入: nums = [-1,0,3,5,9,12], target = 2     输出: -1        解释: 2 不存在 nums 中因此返回 -1 提示: 你可以假设 nums中的所有元素是不重复的. n将在[1, 10000]之间. nums的每个元素

  • C语言详细讲解strcpy strcat strcmp函数的模拟实现

    目录 一.模拟实现strcpy函数 二.模拟实现strcat函数 三.模拟实现strcmp函数 四.小结 一.模拟实现strcpy函数 strcpy函数是字符串拷贝函数,就是将源字符串拷贝到目标空间中. char * strcpy ( char * destination, const char * source );//库函数中的声明 将源(source)指向的c字符串复制到目标(destination)指向的数组中,包括终止的空字符(并在该点停止). 为避免溢出,目标(destination

随机推荐