数组实参的退化

  • 首先明确数组作为形参传递时,如果非引用类型形参,本质上传递的实参为数组的首地址,即会发生退化。
  • 引用式传递时则是传递的是数组整体。
  • 并且此处比较大小,始终是比较的地址大小,而非实际的"hello"或者是"world" 的"h"与"w"的大小。字符串比较可以使用memcmp或者strncmp
 
#include <iostream>
using namespace std;

#define MIN(p1, p2) (p1 < p2 ? p1 : p2)

char* min1(char* p1, char* p2)
{
    cout << "p1 = " << (void*)p1 << "    p2 = " << (void*)p2 << endl;
    return p1 < p2 ? p1 : p2;
}
char* min2(char p1[5] , char p2[5])
{
    cout << "p1 = " << (void*)p1 << "    p2 = " << (void*)p2 << endl;
    cout << typeid(p1).name() << endl;
    return p1 < p2 ? p1 : p2;
}

//数组的引用需要指定参数大小,并且传入实参时会对长度做检查 
const char* min3(const char(&p1)[6] ,const char (&p2)[6] )
{
    cout << typeid(p1).name() << endl;
    return p1 < p2 ? p1 : p2;
}

int main (void) 
{
    //"hello静态存储区,只读常量段",sz1栈中存的"hello"的字符数组 
    char sz1[] = "hello";
    char sz2[] = "world";
    cout << "&"hello" = " << (void*)&"hello" << "    &"world" = " << (void*)&"world" << endl;
    cout << "sz1 = " << (void*)sz1 << "    sz2 = " << (void*)sz2 << endl;
    cout << "**********************************************" << endl;
    cout << "MIN:" << MIN(sz1, sz2) << endl; 
    cout << "**********************************************" << endl;
    cout << "min1:" << min1(sz1, sz2) << endl;
    cout << "**********************************************" << endl;
    cout << "min2:" << min2(sz1, sz2) << endl;
    cout << "**********************************************" << endl;
    cout << "min3:" << min3(sz1, sz2) << endl;
    cout << "**********************************************" << endl;
    cout << (sz1 < sz2 ? sz1 : sz2) << endl;
    cout << "**********************************************" << endl;
    getchar();
    return 0;
}

 测试发现不同编译器输出结果差异较大。如下:

C-Free ==>mingw5:压栈从左向右                                 VS2008==>MSVC :压栈从右向左

 

分析:

  min1,min2结果是由于压栈顺序不同导致。

  MIN, min3结果由于不同编译器内存分配方式不同导致。

  引用型参数传递时,应该传递的是数组的整体,此时比较应该是和定义sz1,和sz2的作用域内比较sz1和sz2的结果是一致的。

  整体上,排除不同编译器的内存使用差异,压栈顺序差异,结论依然符合预期。

  附带知识点:

    1.数组引用形参声明: char (&arr)[10];必须指定size,且使用时传入的实参必须和形参数组的size一致。

    2. ostream输出地址需要先转换成(void*)

    3.数组作为参数传递时,如果不是引用式传递,则不会考虑数组大小。形参char p1[X], X有没有或者多大都没有关系。

    4.至于main局部定义的sz1,和sz2的在栈中的地址先后顺序都不一样,也属于编译器分配内存的方式不一样所致。

原文地址:https://www.cnblogs.com/kuikuitage/p/9310863.html