C++——数组形参退化为指针
数组做形参退化为指针
如果数组作为函数参数,则数组形参会退化为指针,以下代码在编译器看来是等价的
- void fun1(int a[]);
- void fun2(int a[]);
- void fun3(int a[]);
- void fun4(int *a);
- #include<iostream>
- using namespace std;
- void fun1(int a[])
- {
- cout << sizeof(a) / sizeof(a[]) << endl;
- }
- void fun2(int a[])
- {
- cout << sizeof(a) / sizeof(a[]) << endl;
- }
- void fun3(int a[])
- {
- cout << sizeof(a) / sizeof(a[]) << endl;
- }
- void fun4(int *a)
- {
- cout << sizeof(a) / sizeof(a[])<<endl;
- }
- void main(int argc, char* argv[])
- {
- int arr[] = {,,,,,,,,,};
- fun1(arr);
- fun2(arr);
- fun3(arr);
- fun4(arr);
- cout << sizeof(arr) / sizeof(arr[]) << endl;
- system("pause");
- }
数组
- #include<stdio.h>
- void main(int argc, char* argv[])
- {
- int arr[] = {};
- printf("arr=%d, &arr=%d\n", arr, &arr);
- printf("arr+1=%d, &arr+1=%d\n",arr+, &arr+);
- system("pause");
- }
//arr,&arr的数组类型不一样
//arr,数组首元素地址,一个元素4字节,+1,+4
//&arr,整个数组的首地址,一个数组4*10=40字节,+1,+40
char* argv[]和char** argv
- void main(int argc, char* argv[])
- void main(int argc, char** argv)
main函数写成上面2种形式都行,于是有人自然会认为char* argv[]与char** 等价。char* argv[]与char**本质上是不同的,char* argv[]是素组,你可以这样
- char* argv[] = {"hello","world","Linux","NB"}
但是char**就不行,下面代码是语法错误
- char** argv = {"hello","world","Linux","NB"}
指针只能指向一块内存,{"hello","world","Linux","NB"}是4块内存。数组可以指向多块内存。
那为啥在main函数中,2者就等价了呢? 因为数组作为形参,会自动退化为指针。
为啥void a不行,void* a就行
对于出void以外的内置类型,自定义类型。我们可以
- typename var;
- typename* p_var;
但是唯独void不行
- void a; //语法错误
- void* p; //OK
C/C++中类型就像模具,其本身不占用内存,根据模具产生的对象占内存。void a,单纯这一句,编译器无法计算出a到底占用多少内存。void* p就行,这是因为在32位架构下,指针都是4Byte。
二维数组首行地址,和首行首元素地址的值是一样
- #include<stdio.h>
- void main(int argc, char* argv[])
- {
- int i;
- char* str1[] = {"","",""};
- char str2[][] = { "","","" };
- printf("str1=%x, *str1=%x, &(**str1)=%x\n", str1, *str1, &(**str1));
- printf("str2=%x, *str2=%x\n", str2, *str2);
- for (i = ; i < sizeof(str2) / sizeof(str2[]); i++)
- {
- //printf("%s\n",str2+i); 与下一行输出内容一样
- printf("%s\n", *(str2 + i));//*(str2 + i)等价于str2[i]
}
} system("pause"); }
二级指针的内存模型
- #include <string.h>
- #pragma warning(disable:4996) // 等价于_CRT_SECURE_NO_WARNINGS
- int main(int argc, char* argv[])
- {
- int i = ;
- char* p0 = NULL;
- p0 = (char*)malloc(sizeof(char)*);
- strcpy(p0, "Hello World");
- //3个char* ,每个的值都是空
- char* ch_arr[] = { };
- for ( i = ; i < sizeof(ch_arr)/sizeof(ch_arr[]); i++)
- {
- ch_arr[i] = (char*)malloc(sizeof(char)*);
- strcpy(ch_arr[i], "Hello World");
- }
- int arr[];//静态分配
- int *p_arr = (int*)malloc(sizeof(int) * );//等价于arr[10],动态分配
- char* str_arr[] = { };
- char** p_str_arr = (char**)malloc(sizeof(char*) * );
- strcpy(p_str_arr[], "Hello World");
- }
最后一句会报错
- strcpy(p_str_arr[], "Hello World");
出错原因在于向未分配内存的地址拷贝数据,这和7,8行道理一样。
改为如下则不会有问题
- char* str_arr[] = { };
- char** p_str_arr = (char**)malloc(sizeof(char*) * );
- //strcpy(p_str_arr[0], "Hello World");
- for ( i = ; i < ; i++)
- {
- p_str_arr[i] = (char*)malloc(sizeof(char) * );
- strcpy(p_str_arr[i], "Hello World");
- }
此时内存模型
从上图可见,heap实际上分配了2大块,于是释放内存步骤为:
先释放那3个100B,再释放3个4B
- for ( i = ; i < ; i++)
- {
- free(p_str_arr[i]);
- p_str_arr[i] = NULL;
- }
- if (NULL != p_str_arr)
- {
- free(p_str_arr);
- }
如果是函数返回二级指针的情况呢,看如下代码
- #include <string.h>
- #pragma warning(disable:4996) // 等价于_CRT_SECURE_NO_WARNINGS
- char** getBuf(int n)
- {
- int i;
- char** buf = (char**)malloc(sizeof(char*) * );
- //strcpy(buf[0], "Hello World");错误写法
- for (i = ; i < ; i++)
- {
- buf[i] = (char*)malloc(sizeof(char) * );
- strcpy(buf[i], "Hello World");
- }
- return buf;
- }
- void Free(char** buf, int n)
- {
- int i;
- for (i = ; i < n; i++)
- {
- free(buf[i]);
- buf[i] = NULL;
- }
- if (NULL != buf)
- {
- free(buf);
- }
- }
- int main(int argc, char* argv[])
- {
- int n = ;
- int i;
- char** buf = getBuf(n);
- Free(buf, );
buf = NULL;- }
再说释放内存,为啥Free后还要让buff = NULL
- Free(buf, );
- buf = NULL;
C++——数组形参退化为指针的更多相关文章
- C语言 数组名不是指针
今天上计算机系统课的时候老师讲到了C中的聚合类型的数据结构.在解释数组名的时候说"数组名是一个指针,指向该数组的第一个元素",附上ppt(第二行): 我觉得这是不正确的,是一个常见 ...
- CC++语法::数组名退化(array decaying)
参考: CSDN::C/C++中数组名退化为指针的情况 stackoverflow::What is array decaying? 起因 笔者在写memset的时候总想偷一点懒(因为我们一般都是为了 ...
- C语言中,数组名作为参数传递给函数时,退化为指针
C语言中,数组名作为参数传递给函数时,退化为指针 C语言中,数组名作为参数传递给函数时,退化为指针:需要数组大小时, 需要一个参数传数组名,另一个传数组大小. 数组名做函数参数时,就相当于指针了. ...
- C语言 数组做函数参数退化为指针的技术推演
//数组做函数参数退化为指针的技术推演 #include<stdio.h> #include<stdlib.h> #include<string.h> //一维数组 ...
- c 数组做为形參时 该參数退化为指针
当数组做为函数的形參的时候,该參数退化为指针,而且是无法直接求得数组的大小. 传数组给一个函数.数组类型自己主动转换为指针类型,因而传的实际是地址. void func(int array[10]) ...
- sizeof(数组名)和sizeof(指针)
在做这道题时: 32位环境下,int *p=new int[10];请问sizeof(p)的值为()A.4 B.10 C.40 ...
- Linux C\C++基础——数组形参的使用
1.数组形参 ]) void fun(int a[]) void fun(int *a) ],int n) void fun(char*p[],int n) void fun(char**p,int ...
- c语言 数组名是常量指针
//数组名是常量指针 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include ...
- C语言 指针基础篇 数组,函数与指针的运用 2 14
下面看看如何在函数中运用指针吧 下面是往函数传入指针的简单操作,不是传入数组的.判断一个a是否大于b是的话给,是的话对其进行操作,不是的话就直接返回. #include <stdio.h> ...
随机推荐
- Swift学习 (二)
2.控制流: 主要有三种类型的语句 if,switch和新增的guard for,while break,continue 关于if 语句里的条件不再需要使用()包裹了. 1 2 3 4 let nu ...
- C#关于DateTime得到的当前时间的格式和用法
DateTime.Now.ToShortTimeString() DateTime dt = DateTime.Now; dt.ToString();//2005-11-5 13:21:25 dt.T ...
- sqlserver 数据库操作导出数据sql工具
软件名称sqldbx 下载URL https://download.csdn.net/download/yanghl1998/7832861 Navicat Premium 这个工具任何类型数据库 ...
- Spring 分布式事务详解
在学习分布式事务的过程中会遇到以下关键名词: 相关名词: XA :XA规范的目的是允许多个资源(如数据库,应用服务器,消息队列,等等)在同一事务中访问,这样可以使ACID属性跨越应用程序而保持有效.X ...
- 如何抓住ECS的命门,让我们的学习事半功倍
导读 这是一篇老文写与2019年5月 我们说如何提高我们的学习效率,有人说一本书一般只会讲一个知识点,那我们学习ECS 如何抓住学习的重点,提高学习效率.经过本人一段时间的学习总结,总于找到了一个便捷 ...
- Egret入门学习日记 --- 第十二篇(书中 5.1节 内容)
第十二篇(书中 5.1节 内容) 昨天把 第4章完成了. 今天来看第5章. 接下来是 5.1节 的内容. 总结一下 5.1节 的重点: 1.如何制作一个公用按钮皮肤. 跟着做: 重点1:如何制作一个公 ...
- Python爬取链家二手房源信息
爬取链家网站二手房房源信息,第一次做,仅供参考,要用scrapy. import scrapy,pypinyin,requests import bs4 from ..items import L ...
- 解决 OpenCV with CUDA 编译提示缺少 nvcuvid.h 的问题
系统环境: 操作系统:Ubuntu 18.04.01 显卡型号:GeForce GTX 1060 6G CMake 版本:3.10.2 GCC 版本:7.4.0 GNU Make 版本:4.1 CUD ...
- 向量空间模型(Vector Space Model)
搜索结果排序是搜索引擎最核心的构成部分,很大程度上决定了搜索引擎的质量好坏.虽然搜索引擎在实际结果排序时考虑了上百个相关因子,但最重要的因素还是用户查询与网页内容的相关性.(ps:百度最臭名朝著的“竞 ...
- Ant 构建 Jmeter脚本报错详解
在搭建Ant构建Jmeter脚本的时候,小组成员遇到了各种问题. 再这里总结一下,遇到类似问题的可以做个参考 1.提示 does not exist 解决方案: 出现这种的问题原因有很多. 先排除权限 ...