【问题标题】:Is an array argument passed to a function not a constant pointer?传递给函数的数组参数不是常量指针吗?
【发布时间】:2012-04-01 08:45:02
【问题描述】:

考虑代码:

void foo(char a[]){
   a++;            //  works fine, gets compiled
   //... 
}

现在,考虑一下:

void foo(){
   char a[50];
   a++;            //  Compiler error
   //... 
}

听说数组相当于一个常量指针,不能自增,因为它不是左值……

那么为什么要编译第一个代码,是不是因为函数的数组参数作为指针传递,即 T[] 被转换为 T* 以传递.. 因此, foo(a) 将 a 作为指针传递。

但它不是因为被声明为:

而没有再次转换为T[]
void foo(char a[]);

【问题讨论】:

标签: c++ c arrays pointers


【解决方案1】:

当您将数组作为参数传递给函数时,它会衰减为指针。
所以你在函数体内增加的东西是一个指针,而不是一个数组。

【讨论】:

  • 特别是,就好像您声明了char *temp = a;,然后增加了temp
【解决方案2】:

这是从 C 语言继承而来的一个相当不幸的特性,具有“decay”这个相当难听的名称。由于 C 曾经不允许按值传递复合类型,因此他们决定允许程序员将数组指定为函数参数类型,但这只是表面上的。数组类型衰减为指针类型,实现了一种不同于语言其余部分的传递引用语义。丑陋。

回顾一下(其他人已经说过),签名

void foo(char a[]); // asking for trouble

被毫不客气地混入

void foo(char *a);

... 都是为了与古老的 C 代码兼容。由于您不是在编写古老的 C 代码,因此您不应该使用此“功能”。

但是,您可以干净地将 reference 传递给数组。 C++ 要求知道数组的大小:

void foo( char (&a)[ 50 ] );

现在a 不能在函数内修改(编辑:它的内容当然可以——你知道我的意思),并且只能传递正确大小的数组。对于其他所有内容,请传递指针或更高级别的类型。

【讨论】:

    【解决方案3】:

    听说数组等价于常量指针

    可以这样想,但它们并不等同。

    数组在传递给函数时会衰减为指针,这就是为什么在函数内部它是有效的。

    仅仅因为签名是void foo(char a[]) 不会使a 成为一个数组。

    在函数之外,它只是一个数组,你不能对它做指针运算。

    【讨论】:

      【解决方案4】:

      在 C++ 中,任何类型为“T 的数组”的函数参数都被调整为“指向 T 的指针”。试试这个代码:

      void foo(char a[]) {}  
      void foo(char* a) {}  //error: redefinition  
      

      它们确实是相同的功能。

      那么,为什么我们可以将数组参数作为指针参数传递给函数呢?不是因为数组等价于常量指针,而是因为数组类型可以隐式转换为指针类型的右值。还要注意转换的结果是一个右值,这就是为什么你不能将运算符 ++ 应用于数组,你只能将此运算符应用于左值。

      【讨论】:

        【解决方案5】:

        听说数组相当于一个常量指针,不能自增,因为它不是左值……

        差不多了。

        数组表达式不可修改的左值;它可能不是++-- 等运算符的操作数,也可能不是赋值表达式的目标。这与常量指针(即声明为T * const 的指针)不同。

        当数组表达式是sizeof 或一元& 的操作数时,数组表达式将替换为指针表达式,其值为数组的第一个元素的地址except运算符,或者当数组表达式是用于在声明中初始化另一个数组的字符串文字时。

        当你调用带有数组参数的函数时,例如

        int a[N];
        ...
        foo(a);
        

        表达式 a 从“int 的 N 元素数组”类型转换为“指向int 的指针”,这个指针值就是传递给foo 的值;因此,对应的函数原型应该是

        void foo (int *arr) {...}
        

        请注意,在函数参数声明的上下文中,T a[]T a[N]T *a 相同;在所有三种情况下,a 都被声明为指向T 的指针。在函数foo 中,参数arr 是一个指针表达式,它一个可修改的左值,因此它可以分配给++ 和@ 的操作数,也可以是++ 和@ 的操作数987654340@ 运营商。

        记住所有这些转换都在数组表达式上;即数组标识符或引用内存中数组object的其他表达式。数组对象(保存数组值的内存块)不会被转换。

        【讨论】:

          【解决方案6】:

          当您将数组 a[] 传递给函数时,它会将 'a' 的值(一个地址)传递给函数。因此您可以将其用作函数中的指针。如果你在函数中声明一个数组,'a' 是常量,因为你不能改变它在内存中的地址。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-11-07
            • 1970-01-01
            • 1970-01-01
            • 2013-02-15
            • 1970-01-01
            • 2018-08-25
            相关资源
            最近更新 更多