Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么是数组到指针衰减?_C++_C_Arrays_Pointers - Fatal编程技术网

C++ 什么是数组到指针衰减?

C++ 什么是数组到指针衰减?,c++,c,arrays,pointers,C++,C,Arrays,Pointers,什么是数组到指针衰减?与数组指针有什么关系吗?这是当数组腐烂并被指向时;-) 实际上,如果你想在某个地方传递一个数组,但指针却被传递了(因为谁会为你传递整个数组),人们会说可怜的数组会退化为指针。据说数组会“退化”为指针。声明为“代码> int编号[5 ] 的C++数组不能被重新指向,即不能说数字= 0x5A5AF223 < /代码>。更重要的是,衰变一词意味着类型和维度的丧失numbers通过丢失维度信息(计数5)而衰减为int*,并且类型不再是int[5]。在这里找你 如果按值传递数组,那么

什么是数组到指针衰减?与数组指针有什么关系吗?

这是当数组腐烂并被指向时;-)

实际上,如果你想在某个地方传递一个数组,但指针却被传递了(因为谁会为你传递整个数组),人们会说可怜的数组会退化为指针。

据说数组会“退化”为指针。声明为“代码> int编号[5 ] 的C++数组不能被重新指向,即不能说<代码>数字= 0x5A5AF223 < /代码>。更重要的是,衰变一词意味着类型和维度的丧失
numbers
通过丢失维度信息(计数5)而衰减为
int*
,并且类型不再是
int[5]
。在这里找你


如果按值传递数组,那么实际上要做的是复制一个指针-指向数组第一个元素的指针被复制到参数(其类型也应该是数组元素类型的指针)。这是由于阵列的衰变性质;一旦衰减,
sizeof
就不再给出完整数组的大小,因为它实际上变成了指针。这就是为什么(除其他原因外)首选通过引用或指针进行传递

在阵列中通过的三种方式1:

最后两个将提供适当的
sizeof
信息,而第一个不会,因为数组参数已衰减为指定给参数


1在编译时应该知道常量U。

数组基本上与C/C++中的指针相同,但不完全相同。转换阵列后:

const int a[] = { 2, 3, 5, 7, 11 };
插入指针(无需强制转换即可工作,因此在某些情况下可能会意外发生):

您将失去
sizeof
运算符对数组中的元素进行计数的能力:

assert( sizeof(p) != sizeof(a) );  // sizes are not equal
这种失去的能力被称为“衰变”


有关更多详细信息,请查看此项。

数组衰减意味着,当将数组作为参数传递给函数时,它将被等同于指针(“衰减为”)

void do_something(int *array) {
  // We don't know how big array is here, because it's decayed to a pointer.
  printf("%i\n", sizeof(array));  // always prints 4 on a 32-bit machine
}

int main (int argc, char **argv) {
    int a[10];
    int b[20];
    int *c;
    printf("%zu\n", sizeof(a)); //prints 40 on a 32-bit machine
    printf("%zu\n", sizeof(b)); //prints 80 on a 32-bit machine
    printf("%zu\n", sizeof(c)); //prints 4 on a 32-bit machine
    do_something(a);
    do_something(b);
    do_something(c);
}
上述情况有两种复杂情况或例外情况

首先,在处理C和C++中的多维数组时,只有第一维丢失了。这是因为数组在内存中是连续排列的,所以编译器必须知道除了第一个维度以外的所有维度,才能计算到该内存块中的偏移量

void do_something(int array[][10])
{
    // We don't know how big the first dimension is.
}

int main(int argc, char *argv[]) {
    int a[5][10];
    int b[20][10];
    do_something(a);
    do_something(b);
    return 0;
}

第二,在C++中,可以使用模板来推断数组的大小。微软使用C++版本的安全CRT函数,你可以使用类似的技巧来可靠地进行。

数组,在C中,没有任何价值。 如果需要对象的值,但对象是数组,则使用其第一个元素的地址,类型

指针指向(数组元素类型)

在函数中,所有参数都按值传递(数组也不例外)。当你在一个函数中传递一个数组时,它“衰减为指针”(原文如此);当你将一个数组与其他数组进行比较时,它再次“衰减为指针”(原文如此)

函数foo需要数组的值。但是,在C中,数组没有任何价值!因此
foo
取而代之的是数组第一个元素的地址

int arr[5];
int *ip = &(arr[1]);
if (arr == ip) { /* something; */ }
在上面的比较中,
arr
没有值,因此它成为指针。它成为指向int的指针。该指针可以与变量
ip
进行比较

在您习惯于看到的数组索引语法中,arr再次“衰减为指针”

arr[42];
/* same as *(arr + 42); */
/* same as *(&(arr[0]) + 42); */

数组不衰减为指针的唯一时间是当它是sizeof运算符的操作数,或&operator(“address of”运算符),或作为用于初始化字符数组的字符串文字时。

以下是标准所述(C99 6.3.2.1/3-其他操作数-左值、数组和函数指示符):

除非它是sizeof运算符或一元&运算符的操作数,或是 字符串文字用于初始化数组,类型为“”的数组类型“”的表达式为 已转换为类型为“指向类型的指针”且指向的初始元素的表达式 数组对象,并且不是左值

这意味着只要在表达式中使用数组名,它就会自动转换为指向数组中第一项的指针

int arr[5];
int *ip = &(arr[1]);
if (arr == ip) { /* something; */ }
请注意,函数名的作用方式与此类似,但函数指针的使用要少得多,而且使用的方式更为专门,因此它不会像数组名到指针的自动转换那样引起混乱

C++标准(4.2数组到指针转换)将转换要求放宽到(强调雷):

“NT数组”或“T未知界数组”类型的左值或右值可以转换为右值 类型为“指向T的指针”

因此,转换不必像在C语言中一样发生(这使函数重载或模板与数组类型匹配)

这也是为什么在C中应该避免在函数原型/定义中使用数组参数的原因(在我看来,我不确定是否有任何普遍的一致性)。它们会导致混淆,而且无论如何都是虚构的-使用指针参数,混淆可能不会完全消失,但至少参数声明没有说谎。

“衰退”是指表达式从数组类型隐式转换为指针类型。在大多数上下文中,当编译器看到数组表达式时,它会将表达式的类型从“T的N元素数组”转换为“指向T的指针”,并将表达式的值设置为数组第一个元素的地址。此规则的例外情况是,数组是
sizeof
&
运算符的操作数,或者数组是在声明中用作初始值设定项的字符串文字

假设以下代码:

char a[80];
strcpy(a, "This is a test");
表达式
a
的类型为“字符的80元素数组”,并且
arr[42];
/* same as *(arr + 42); */
/* same as *(&(arr[0]) + 42); */
char a[80];
strcpy(a, "This is a test");
char *strcpy(char *dest, const char *src);
char a[80];
char *ptr_to_first_element = a;
char (*ptr_to_array)[80] = &a;
a[i] == ptr_to_first_element[i] == (*ptr_to_array)[i] != *ptr_to_array[i] != ptr_to_array[i]
sizeof a == sizeof *ptr_to_array == 80
sizeof *ptr_to_first_element == sizeof (char) == 1
sizeof ptr_to_first_element == sizeof (char *) == whatever the pointer size
                                                  is on your platform