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> ...
随机推荐
- ubuntu18.04 server配置静态ip,新的网络工具netplan的使用方法【转:http://forum.ubuntu.org.cn/viewtopic.php?t=487463】
最新发布的ubuntu18.04 server,启用了新的网络工具netplan,对于命令行配置网络参数跟之前的版本有比较大的差别,现在介绍如下:1.其网络配置文件是放在/etc/netplan/50 ...
- 记EXSI虚拟机CentOS7断电无法启动修复过程
参考:https://msd.misuland.com/pd/3148108429789233656 EXSI6.7安装虚拟机CentOS7.5 1804 断电后启动页面进度条很慢 最后出现如下提示 ...
- 查看某个进程PID对应的文件句柄数量,查看某个进程当前使用的文件句柄数量
================================ 1.linux所有句柄查询 lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more ...
- 根据start和limit从已有的数据列表中获取从start开始的limit个数据
代码记录(需求:根据start和limit从已有的数据列表中获取从start开始的limit个数据) 已有的数据列表:这个数据列表是经过处理的,可能是在SQL查询时无法处理的如多条件排序,而排序条件需 ...
- H5本地存储(转)
H5本地存储 一.本地存储由来的背景 众所周知Html4时代Cookie的大小.格式.存储数据格式等限制,网站应用如果想在浏览器端存储用户的部分信息,那么只能借助于Cookie.但是 ...
- UIPath工具里面如何入力一览里面的数据
问题描述: UIpath工具如何在网页里面入力一览多条的数据.例如:某个公司里面在自己的内部员工管理的软件里面手动入力公司员工的所有信息之后反馈到数据库当中. 解决方法: UIpath工具来入力数据, ...
- [转帖]Linux修改时区的正确方法
Linux修改时区的正确方法 /etc/localtime 以及timedatectl 两种方式修改时区. CentOS和Ubuntu的时区文件是/etc/localtime,但是在CentOS7以后 ...
- [转帖]年度网络攻击大调查:SSH端口最易受网络攻击,HTTPS其次!
年度网络攻击大调查:SSH端口最易受网络攻击,HTTPS其次! https://zhuanlan.kanxue.com/article-9431.htm 一般来说,人们会通过检查端口.更新设备等多种措 ...
- FishingMaster(HDU-6709)【贪心】
题目链接:https://vjudge.net/problem/HDU-6709 题意:一个人要抓n条鱼,每抓一条鱼用时K,每烹饪一条鱼用时a[i],抓鱼的过程不能被打断,烹饪鱼的时候可以抓鱼,也可以 ...
- Idea生成的的第一个eureka注册中心服务器
操作: 1.file->new->project Spring Initializer ->default 点击next 2.输入 Group ...