为什么数组的大小和指向第一个元素的指针是不同的?

时间:2015-08-19 15:38:08

标签: c arrays pointers

Kernighan&里奇第二版。表示:

  

索引和指针算术之间的对应关系非常接近。根据定义,类型数组的变量或表达式的值是数组的元素零的地址。因此在任命后   pa = &a[0];

     

paa具有相同的值。由于数组的名称是初始元素位置的同义词,因此赋值pa=&a[0]可以也写成
  pa = a;

如果apa相同,那么为什么这段代码:

#include <stdio.h>

int main()
{
    char a[] = "hello";
    char *pa = a;
    printf("Array: %ld\n", sizeof(a));
    printf("Pointer: %ld\n", sizeof(pa));
}

输出:

Array: 6
Pointer: 8

非常感谢参考权威来源。

5 个答案:

答案 0 :(得分:3)

两个对象可以具有相同的地址,但它们的大小可以不同。

来自C标准(6.5.3.4 sizeof和alignof运算符)

  

2 sizeof运算符产生其操作数的大小(以字节为单位)   可以是表达式或类型的带括号的名称。 尺寸是   根据操作数的类型确定 ....

考虑以下示例

#include <stdio.h>

int main( void )
{
    struct A
    {
        char c;
        int x;
    } a;

    printf( "object a:\taddress - %p size - %zu\n",
            &a, sizeof( a ) );
    printf( "object a.c:\taddress - %p size - %zu\n",
            &a.c, sizeof( a.c ) );
}    

程序输出

object a:   address - 0x7fff164e16d0 size - 8
object a.c: address - 0x7fff164e16d0 size - 1

可以看到a类型的对象struct A及其c类型的数据成员char具有相同的地址但大小不同。

对于数组,指针是一个存储其他对象地址的对象。要存储其他对象的地址,只需为指针分配4或8个字节的内存即可,具体取决于所使用的系统。

对于数组,它们被命名为内存范围。数组不存储地址。他们存储自己的元素(当然可以是指针)。

表达式中使用的数组名称将转换为指向其第一个元素的指针。

根据C标准(6.3.2.1 Lvalues,数组和函数指示符)

  

3除非它是sizeof运算符或一元&amp;的操作数。   operator,或者是用于初始化数组的字符串文字, an   具有类型''数组类型''的表达式将转换为   带有''指向类型''的指针的表达式,指向初始值   数组对象的元素,而不是左值。如果是数组对象   具有寄存器存储类,行为未定义。

在此引用中列出了何时未将数组转换为指向其第一个元素的指针。例如,当数组是sizeof运算符的操作数时。

如果要返回您的计划

int main()
{
    char a[] = "hello";
    char *pa = a;
    printf("Array: %ld\n", sizeof(a));
    printf("Pointer: %ld\n", sizeof(pa));
}

然后在本声明中

    char a[] = "hello";

类型为"Hello"的字符串文字char[6]未转换为指针。 但是在这个声明中

    char *pa = a;

数组a被转换为指向其第一个元素的指针。

在本声明中

    printf("Array: %ld\n", sizeof(a));

数组a未转换为指针,因为它是sizeof运算符的操作数。

但是,如果您在sizeof运算符中使用了一个表达式,例如像

那样
sizeof( a + 0 )

然后你会得到一个指针,相应地sizeof将返回指针的大小而不是数组的大小

答案 1 :(得分:2)

他们确实拥有相同的。但意味着它们是相同的。

a 固定大小的数组。 pa 仍是指针。

sizeof是一个识别这种差异的运算符。

您的数组有6个大小为char的元素(sizeof(char)由标准定义为1)。 (第6个元素是字符串null终止符)。

您的系统上

sizeof(char*)为8。它可能是64位。

答案 2 :(得分:2)

数组不是指针。在许多情况下,数组名称​​衰减指向其第一个元素的指针,但sizeof是少数例外之一。

  

C11§6.3.2.1左值,数组和函数指示符

     

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

答案 3 :(得分:1)

apa不相同。永远记住:数组不是指针。当在表达式中使用时,数组被转换为指向其第一个元素的指针,但有一些例外,包括作为sizeof运算符的操作数。
sizeof(a)将给出数组的大小,而sizeof(pa)将给出指针的大小。

答案 4 :(得分:1)

 char a[] = "hello";
 char *pa = a;

此处sizeof(a)会给出数组a的大小。而sizeof(pa)会给出指针pa的大小。两者都不同。

同样在函数参数中,数组衰减到指针但是这一个与&一起是异常。

同样在打印类型size_t时,您应该使用说明符%zu(在ANSI C99中指定)。