Fork me on GitHub

C++——数组形参退化为指针

数组做形参退化为指针

如果数组作为函数参数,则数组形参会退化为指针,以下代码在编译器看来是等价的

void fun1(int a[100]);
void fun2(int a[1]);
void fun3(int a[]);
void fun4(int *a);
#include<iostream>
using namespace std;
void fun1(int a[100])
{
    cout << sizeof(a) / sizeof(a[0]) << endl;
}
void fun2(int a[1])
{
    cout << sizeof(a) / sizeof(a[0]) << endl;
}
void fun3(int a[])
{
    cout << sizeof(a) / sizeof(a[0]) << endl;
}
void fun4(int *a)
{
    cout << sizeof(a) / sizeof(a[0])<<endl;
}
void main(int argc, char* argv[])
{
    int arr[] = {10,9,8,7,6,5,4,3,2,1};
    fun1(arr);
    fun2(arr);
    fun3(arr);
    fun4(arr);
    cout << sizeof(arr) / sizeof(arr[0]) << endl;
    system("pause");
}

数组

#include<stdio.h>

void main(int argc, char* argv[])
{
    int arr[10] = {0};
    printf("arr=%d, &arr=%d\n", arr, &arr);
    printf("arr+1=%d, &arr+1=%d\n",arr+1, &arr+1);
    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[3] = {"111","222","333"};
    char str2[3][3] = { "444","555","666" };
    printf("str1=%x, *str1=%x, &(**str1)=%x\n", str1, *str1, &(**str1));
    printf("str2=%x, *str2=%x\n", str2, *str2);
    for (i = 0; i < sizeof(str2) / sizeof(str2[0]); i++)
    {
        //printf("%s\n",str2+i); 与下一行输出内容一样
        printf("%s\n", *(str2 + i));//*(str2 + i)等价于str2[i]
}
} system("pause"); }

二级指针的内存模型

 1 #include <string.h>
 2 #pragma warning(disable:4996)  // 等价于_CRT_SECURE_NO_WARNINGS
 3 int main(int argc, char* argv[])
 4 {
 5     int i = 0;
 6     char* p0 = NULL;
 7     p0 = (char*)malloc(sizeof(char)*100);
 8     strcpy(p0, "Hello World");
 9 
10     //3个char* ,每个的值都是空
11     char* ch_arr[3] = { 0 };
12     for ( i = 0; i < sizeof(ch_arr)/sizeof(ch_arr[0]); i++)
13     {
14         ch_arr[i] = (char*)malloc(sizeof(char)*100);
15         strcpy(ch_arr[i], "Hello World");
16     }
17 
18     int arr[10];//静态分配
19     int *p_arr = (int*)malloc(sizeof(int) * 10);//等价于arr[10],动态分配
20 
21     char* str_arr[3] = { 0 };
22     char** p_str_arr = (char**)malloc(sizeof(char*) * 3);
23     strcpy(p_str_arr[0], "Hello World");
24 }

最后一句会报错

strcpy(p_str_arr[0], "Hello World");

出错原因在于向未分配内存的地址拷贝数据,这和7,8行道理一样。

改为如下则不会有问题

char* str_arr[3] = { 0 };
char** p_str_arr = (char**)malloc(sizeof(char*) * 3);
//strcpy(p_str_arr[0], "Hello World");
for ( i = 0; i < 3; i++)
{
    p_str_arr[i] = (char*)malloc(sizeof(char) * 100);
    strcpy(p_str_arr[i], "Hello World");
}

此时内存模型

从上图可见,heap实际上分配了2大块,于是释放内存步骤为:

先释放那3个100B,再释放3个4B

for ( i = 0; i < 3; 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*) * 3);
    //strcpy(buf[0], "Hello World");错误写法
    for (i = 0; i < 3; i++)
    {
        buf[i] = (char*)malloc(sizeof(char) * 100);
        strcpy(buf[i], "Hello World");
    }
    return buf;
}
void Free(char** buf, int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        free(buf[i]);
        buf[i] = NULL;
    }
    if (NULL != buf)
    {
        free(buf);
    }
}
int main(int argc, char* argv[])
{
    int n = 3;
    int i;
    char** buf = getBuf(n);
    Free(buf, 3);
buf = NULL; }

再说释放内存,为啥Free后还要让buff = NULL

Free(buf, 3);
buf = NULL;

 

posted @ 2019-03-01 10:00  克拉默与矩阵  阅读(1508)  评论(0编辑  收藏  举报