首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

【C 语言】数组作为参数退化为指针问题 ( 问题描述 | 从编译器角度分析该问题 | 出于提高 C 语言执行效率角度考虑 | 数组作为参数的推荐方案 )

文章目录 一、问题描述 二、从编译器角度分析该问题 三、数组作为参数的推荐方案 一、问题描述 ---- 将 数组 作为 函数参数 , 传递时会 退化为指针 ; 数组的首地址 , 变为指针地址 , 函数中无法判定数组的大小...形参的 array 当做指针 , 只给该形参分配了 4 字节内存 , 没有为其分配 4 x 3 = 12 字节的内存 ; 编译器会将 形参中的数组 作为指针处理 , 只会为其分配 指针 所占用的内存...; 如果 编译器 将 形参作为 数组处理 , 需要 将数组中的所有元素 , 都要拷贝到栈中 , 如果这个数组很大 , 有几千上万个元素 , 那么该函数的执行效率就很低了 ; 因此 , 为了提升 C 语言的执行效率..., 参数传递时 , 如果要传递大量数据 , 不允许传递数组 , 只能传递指针 ; C 语言的优势 , 就是在 调用函数 之间 , 通过指针操作内存 , 效率很高 , 因此 编译器不允许使用数组作为参数...; 三、数组作为参数的推荐方案 ---- 形参设置为 数组元素类型的指针 , 以及数组元素个数 ; 代码示例 : #include /* * 数组作为参数 会 退化为指针 *

69510

C指针基础概览

C指针概述 在C语言中,指针不仅可以表示变量的地址,而且还可以存储数组,数组元素,函数,文件设备的地址,C指针的主要特征具体如下: 通过一个变量声明时在前面使用“*号”,表面这是个指针型变量。...原因在于,这个复制版本身存储在程序栈种,程序运行完毕后会释放栈空间。 传址是指参数是复合类型(数组,结构等)或者指针,传递给函数的是参数的内存地址,利用该地址,可以改变参数的值。...studio 2019中运行的结果为 15 程序中mysum函数接受2个参数,第一个参数是数组长度,第二个参数是指向数组的指针,目前没有较好的检查C语言的数组访问越界问题,所以最好的办法就是把数组的长度直接传给被调用的函数...函数指针 函数指针 C语言中的数据变量无论是在程序栈还是堆中,都拥有自己的内存地址,函数也一样,函数的代码也需要调入内存才能够被执行,它们在内存中也拥有自己的起始地址,因此可以定义指针指向函数,存储函数的起始地址...总结 指针是C语言的核心,使用得当会大大提高程序的编写与运行效率。在C语言中指针不仅仅可以表示变量的地址,而且还可以存储数组,数组元素,函数,文件设备的地址等。

1.1K20
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    一篇读懂 C 指针

    # 函数的形参声明 在 C 语言中,数组不能被整体操作,也就是说,不能直接将一个数组赋值给另一个数组,或者将数组作为参数传递给其他函数。那么,如果我们想把一个数组传递给函数,该怎么做呢?...不管选择哪种方法,在函数内部事实上获得的都是一个指针。 也就是说,在函数的形参声明中,无法声明一个真正的数组,只能声明指针,即使写成数组的形式,编译器也当做指针对待。...# 将数组作为参数传递 在 C 语言中其实是不可以将数组作为参数传递的,但是通过传递指向数组初始元素的指针,可以达到与传递数组相同的效果。...在 main 函数的定义中: 1 int main(int argc, char *argv[]) argc 表示命令行参数的个数。...由于在函数的参数列表中,数组会被视作指针,所以写成下面这样也是一样的: 1 int main(int argc, char **argv) argv[i] 指向每个命令行参数字符串(长度不固定),而

    13410

    FFmpeg 工程之路-基础开发概述

    常量与变量 C语言内存管理 C语言指针 与 数组 C语言指针 数组 C 指针程序demo->testpoint.c C 自定义类型 结构体 枚举类型 C语言文件操作 文件操作流程 C语言操作文件实操-...存储在缓冲区中,并没有写入到文件当中 2、C语言基础回顾 2.1 C语言基础回顾-helloworld 编写helloworld.c源代码 //import 库函数 #include //程序运行主入口 argc 输入一些参数、字符数组每一项都是一个命令参数,这个是行参 int main(int argc,char *argv[]){ printf("hello world...4、c语言指针 与 数组 4.1 c语言指针 指针是c语言的灵魂、所谓指针就是 内存地址 void* 、char* 拿到指针就可以操作(获取、更改)指针指向的内存地址的value、 即 地址 就是 指针...,1,13,file); //5.将文件末尾游标复位到文件最开头的位置,否则 将文件中内容读取到空buf时,buf中数据为空 rewind(file); //6.将file中内容读取到

    49120

    2.1 CC++ 使用数组与指针

    C/C++语言是一种通用的编程语言,具有高效、灵活和可移植等特点。...C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。...C/C++语言具有很高的效率和控制能力,但也需要开发人员自行管理内存等底层资源,对于初学者来说可能会有一定的难度。 定义并使用一维数组: 该数组是最通用的数组,也是最基本的....指针作为函数参数传递: 将指针直接作为函数参数传递,此时函数中接收到的就是数组的首地址....<< ref << std::endl; return 0; } 多级指针做函数参数: 如下代码中PrintArray()函数传递了一个常量形式的二级指针作为参数,常量不可被修改.

    29760

    2.1 CC++ 使用数组与指针

    C/C++语言是一种通用的编程语言,具有高效、灵活和可移植等特点。...C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。...C/C++语言具有很高的效率和控制能力,但也需要开发人员自行管理内存等底层资源,对于初学者来说可能会有一定的难度。定义并使用一维数组: 该数组是最通用的数组,也是最基本的....: 将指针直接作为函数参数传递,此时函数中接收到的就是数组的首地址....; return 0;}多级指针做函数参数: 如下代码中PrintArray()函数传递了一个常量形式的二级指针作为参数,常量不可被修改.

    31530

    exception: access violation reading 0xFFFFFFFFFFFFFFFF

    异常:访问无法读取的地址 0xFFFFFFFFFFFFFFFF在编程过程中,我们常常会遇到各种异常情况。...本文将探讨该异常的原因和解决方法。异常原因这个异常的原因通常是因为程序试图访问一个不存在的内存地址,即一个非法的指针。在现代操作系统中,内存被分为多个页,每页有一个唯一的地址。...当一个指针的值为 NULL 或者 0 时,如果我们试图读取该指针指向的内存,则会引发该异常。解决这个问题的方法是确保指针被正确初始化,并且在使用之前进行有效性检查。...数组越界访问如果我们试图访问一个数组超出其边界的索引,则会引发该异常。例如,对于一个长度为 N 的数组,如果我们尝试访问索引为 N 或者更大的位置,就会导致访问无法读取的地址异常。...使用空指针的一个常见场景是在动态内存分配时,当内存分配失败时,返回一个空指针作为错误标志。例如,在C++中,当使用new来进行对象的动态内存分配时,如果内存不足或发生其他错误,将返回一个空指针。

    1.7K10

    iOS底层原理总结 - 探寻OC对象的本质

    (8字节) 方式二:通过lldb指令xcode自带的调试器 memory read 0x10074c450 // 简写 x 0x10074c450 // 增加读取条件 // memory read/...lldb读取内存 那么一个NSObject对象占用多少内存?...但是因为内存对齐的原因。使person对象也占用16个字节。 编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能是该基本数据类型的整倍的位置,作为结构体的首地址。...对象的isa指针指向哪里 当对象调用实例方法的时候,我们上面讲到,实例方法信息是存储在class类对象中的,那么要想找到实例方法,就必须找到class类对象,那么此时isa的作用就来了。...当类对象调用类方法的时候,同上,类方法是存储在meta-class元类对象中的。

    1.2K50

    深入理解CC++中的指针

    但是上面的例子定义函数指针的方法在某些编译器中是无法通过的,最好通过typedef关键字定义函数指针,推荐的写法如下: ?...但是这是单个函数的情况,在C++中取类的方法函数的地址时,这个&符号式不能省略的,见下面的例子: ? 函数指针的另外一个用处,而且是用的最多的,就是作为一个函数的参数。...指针变量的定义方法 先插播一段广告,说下main函数的返回值问题,如下图: ? 这种main函数无返回值的写法,在国内各大C/C++教材上屡见不鲜,这种写法是错误的!   ...C++之父Bjarne Stroustrup在他的主页FAQ中明确地写了这样一句话: 在C++中绝对没有出现过void main(){ /* ... */ } 这样的函数定义,在C语言中也是。...在C99标准规定,只有以下两种定义方式是正确的的: 1 int main(void); 2 int main(int argc,char *argv[]); 虽然在C和C++标准中并不支持void main

    1K10

    OC学习3——C语言特性之指针

    &:取地址运算符,单目运算符,后面通常紧跟一个变量,该运算符用于读取该变量所在的内存地址。 *:取变量运算符,单目运算符,后面通常紧跟一个指针变量,该运算符用于读取该指针变量所指向的内存中的变量。...所以,将数组变量作为参数传递到函数中实际上是一种地址传递。...char* str = "I love IOS" ; C语言的自字符串在底层依然是才用字符数组进行保存的,而str则是一个char*型的指针变量,它指向该字符数组的第一个元素,也就是指向该字符数组的首地址...但是当函数返回一个指针的时候需要注意,由于函数返回的指针只保存了一个地址值,如果该指针指向的是被调用函数中的局部变量,这就非常危险了,因为函数中的局部变量在函数调用结束之后会被自动释放,这样会导致该内存中所保存的数据是不确定的...9、指针数组是值数组中的每个元素都是一个指针变量,常见的main()函数的形参第二个参数定义是char* argv[]就是一个指针数组。

    1.5K80

    【嵌入式开发】C语言 命令行参数 函数指针 gdb调试

    C语言命令行参数详解 命令行参数 : 有两个参数 int argc 和 char **argv; -- argc : 标示输入的参数个数, 注意命令本身也是参数; -- argv : 指向 字符串数组的指针...char *line 指针指向的数组中 * 注意字符串最大为50个, 字符最多有49个, 剩下的最后一位存放 '\0' * 从标准输入流中读取字符, 放到数组中 * 停止读取字符条件 : 个数到达...输入的过滤参数, 即argv 的非 可选参数, 在遍历可选参数的时候, 会对argv进行一系列的自增操作, 如果我们传入的是argv二级指针, 那么在函数中进行的自增操作不会改变argv值, 这里我们需要改变...调用函数指针方法 : (*get_char)(); (3) 使用函数指针示例 示例需求 :  -- 获取字符串数组 : 从标准输入流中读取字符串数据, 将字符串放入字符串数组 char **; --...复杂声明 C语言声明运算符优先级 : C语言中, * 运算符的优先级低于 (); char (*array)[13] 解析: 声明一个指针; -- *array : 代表 array 定义的是一个指针;

    62730

    关于CC++ 一些自己遇到的问题以及解惑

    首先可以告诉大家的是对于单纯的C语言,main里面的参数对于我们学习C来说,并不重要,标准形式有两种int main(int argc,char* argv[])和int main(void),在实际的学习使用中...由于我们的main函数不被其他函数调用(注意:不是不可调用,是一般情况下不调用,如果你想挨骂的话…),所以就不能像其他函数一样,在程序运行中获取参数数据,那为什么还要有这个参数呢,实际上,这个参数是程序运行时...,利用操作系统传进来的,argc代表着指针数组的元素个数,argv[0]是程序所在计算机的完整路径,例如: C:\Users\fdog\Desktop\hello.exe。...总不能在代码中固定一个路径吧,大家计算机名字都不一样,这样肯定行不通,于是我们在代码中开始写到cout的路径”; 然后开始读取用户输入的路径,那么有没有进一步提升用户体验的写法?...这时我们就可以用到main的参数了,利用argv[0]获取该程序的路径,并通过算法解析,即可得到用户把exe放在哪里,那么我们在exe所在的路径下保存数据文本即可,这样就会提示用户体验。

    67641

    ios 底层原理 : 类与类结构分析

    %@ %@",person,teacher); } return 0; } 元类 首先我们通过案例的 lldb 引出元类 在 main 中的 LGTeacher 处加一个断点,运行...这里就该提到两个结构体:objc_class & objc_object 下面在这两个结构体的基础上,对上述问题进行探索 在上一篇底层 7中,从 clang 编译过的main.m 文件,可以看到以下...,p1 是指向[LGPerson alloc]创建的空间地址,既内存地址,p2 同理 &p1,&p2 是指向 p1,p2 指针的指针,也就是二级指针 其指针的指向如下图所示...,即数组名等于首地址 &c和&c[1]地址相差4个字节,主要是因为存储的数据类型 可以通过首地址加偏移量,取出数组中其他元素,其中偏移量是数组的下标,内存中的首地址实际移动的字节数,等于偏移量*数据类型字节数...类的实例方法存储在类的bits属性中 类的类方法存储在元类的bits属性中

    63020

    借问变量何处存,牧童笑称用指针,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang类型指针(Pointer)的使用EP05

    指针变量最大的特点就是存储的某个实际变量的内存地址,通过记录某个变量的地址,从而间接的操作该变量。     & 关键字可以从一个变量中取到其内存地址。     ...func main() { a := [3]int{89, 90, 91} modify(&a) fmt.Println(a) }     程序返回: [90 90 91]     虽然可以用指针传递给一个数组作为方法的实参并对其进行修改...,如果我们想通过一个函数改变一个数组的值,可以将该数组的切片当作参数传给函数,也可以将这个数组的指针当作参数传给函数,显而易见,使用切片更加方便。    ...结语     简而言之,很多编译型语言都在事实上存在指针,c/c++是真实的指针,而Java中其实是指针的引用,可以理解为不能操作指针的值,不允许指针运算的指针。...现实问题是,go lang这种“次时代”的新潮流编程语言,为什么不像Java那样,仅仅实现“引用”,而一定非得给出“指针”的实质概念呢?

    46140

    再议 C 语言中的指针与数组(4)

    2.1 指向数组的指针 2.2 指向复合常量的指针 2.3 通过指针对数组进行操作 2.4 指针与数组在函数定义中的使用 2.5 多维数组与指针 三 总结 再议 C 语言中的指针与数组(4) 一 概述...在本文中,结合数组,再次对指针进行回顾。 二 数组与指针 在 C 语言中,指向数组的指针是比较常见的,也是非常方便和适用的。...2.4 指针与数组在函数定义中的使用 在函数定义时,数组可以使用指针或显示声明来定义形式参数。...多维数组是不能以数组名直接作为指针指向的对象,需要稍微做一些调整才能使用数组名作为指针。在 C 语言中,多维数组实际上就是以一维数组来进行处理的。...在实际的使用过程中要特别谨慎。 3.2 指针是 C 语言中的精华。作为一名 C 语言学习者,指针虽然比较坑,但是这个是无法逃避的,必须花大量的时间与精力去学习与理解。

    1.5K30

    初阶指针和结构体

    平时口语中说的指针,通常指的就是指针变量,是用来存放内存地址的变量。即指针就是地址,口语中的指针通常指的就是指针变量。...但是野指针和有效指针变量保存的都是数值,为了标志此指针变量没有指向任何变量(空闲可用),C语言中可以把NULL赋值给此指针,空指针是指内存地址编号为0的空间。...main函数的形参 int main(int argc,char* argv[]) 1.main函数是操作系统调用的,第一个参数标明argc数组的成员数量,argv数组的每个成员都是char* 类型....2.argv是命令行参数的字符串数组. 3,argc代表命令行参数的数量,程序名字本身算一个参数....#include argc: 传参数的个数(包含可执行程序) argv:指针数组,指向输入的参数 int main(int argc, char *argv[]) { 指针数组

    51430

    你必须知道的指针基础-6.内存的初始化及结构体的使用

    在C语言中,可以采用如下的两种方法:   (1)使用memset函数首先清理一下内存: void *memset(void *s, int ch, unsigned n); 将s所指向的某一块内存中的每个字节的内容全部设置为...); return 0; }   在main函数中,我们声明了一个刚刚定义的结构体p1,但是我们并没有进行初始化。...所谓地址,就是一个数字,那么这里就是一个整形数字代表内存地址,因此,它占4个字节,4+4+8=16。   那么,问题又来了,假如我在main函数中,给name赋值了一个很长很长的字符串呢?...三、结构体的拷贝赋值问题 3.1 结构体的复制其实是“深拷贝”   在C语言中,结构体的复制其实就是将整体拷贝一份而不是将地址拷贝一份,这与在.NET中的深拷贝的概念是类似的(深拷贝和浅拷贝是.NET...,且在文章页面明显位置给出原文链接。

    68330

    汇编和栈

    在下一单元中,您将使用本章中的知识在 LLDB 中构建命令,该命令将通过在内存中抓取函数来发现一些有趣的事情。...还有一个重要的寄存器是基址指针寄存器(RBP),在执行在方法 / 函数内部时有多种用途,程序使用 RBP 的偏移量来访问局部变量或函数参数。...此 C 函数将一个整数作为参数,并用汇编语言编写(AT&T 汇编语言,记住要能够找到源操作数和目标操作数的正确位置),并且位于 StackWalkthrough.s 中。...奇怪的格式是由于该命令在 gdb 中的常用,您看到此命令语法已移植到 lldb 中,从而使从调试器的转换更加容易。...包含 RSP 和可选值的方括号表示取消引用,就像 C 编程中的 * 一样。上面的第一行说 “将 0x7 放入 RSP 指向的内存地址中。”

    3.7K20

    【C语言】 C 语言 关键字分析 ( 属性关键字 | 常量关键字 | 结构体关键字 | 联合体关键字 | 枚举关键字 | 命名关键字 | 杂项关键字)

    【嵌入式开发】C语言 指针数组 多维数组 2.【嵌入式开发】C语言 命令行参数 函数指针 gdb调试 3.【嵌入式开发】C语言 结构体相关 的 函数 指针 数组 4....("%d\n", method_3()); //无法调用 test_2.c 中的静态方法, 编译时会报错....("%d\n", method_3()); //无法调用 test_2.c 中的静态方法, 编译时会报错....s //memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法 //实现方法 : //1.接收参数 : void *s 内存地址, int ch 每个字节赋值内容...: 1.只读数组 : const 修饰数组时, 这个数组是只读的, 数组中的每个元素都是只读的, 不能作为左值; 2.const 数组所在空间不可改变 : 数组所在的空间是不可更改的, 但是通过指针是可以修改数组中每个元素的值的

    2.4K20
    领券