【C语言回顾】C语言中数组名称真的是指针吗?

500 阅读2分钟

指针和数组

数组的本质

#include <stdio.h>
#include <string.h>

int main()
{
    int a[3] = {1, 2, 3};

    printf(" %d \n", *a);
    printf(" %d \n", *(a + 1));

    printf(" %p \n", &a[0]);
    printf(" %p \n", &a);
    printf(" %d \n", sizeof(a));

    //error: 'int *' with an expression of type 'int (*)[3]'
    // int *p1 = &a;

    int (*p)[3] = &a;

    return 0;
}

运行结果如下:

 1 
 2 
 0x7ffee54be5bc 
 0x7ffee54be5bc

结论:

  • 数组名称 a 指向数组的首元素地址(一般情况下)
  • 数组名称 a 可以像指针一样操作
  • &a 是指针数组的指针,类型为 int (*p)[3],这种情况下 a 不能被看成是首元素的地址
  • sizeof(a) 的情况下 a 不能被看成是首元素的地址
  • int *p1 = &a 会直接报错, 'int ' with an expression of type 'int ()[3]'

所以数组名称只有在被看为是数组首元素地址的时候,可以像操作指针一样操作。

字符指针和字符数组的区别

#include <stdio.h>
#include <string.h>

char *test1();
char *test2();
int main()
{
    printf(" %s \n", test1());
    printf(" %s \n", test2());

    char *p = "hello world";
    p = "hello c";

    char pa[12] = "hello world";
    // array type 'char [12]' is not assignable
    // pa = "hello c";

    return 0;
}

char *test1()
{
    char *p = "hello world";
    return p;
}

// warning: address of stack memory associated with local variable 'p' returned [-Wreturn-stack-address]
char *test2()
{
    char p[] = "hello world";
    return p;
}

运行结果如下

hello world 
 � 

结论

  • 字符指针test1中,是一个指向常亮字符串地址的指针,字符数组,内存申请在堆上,返回直接返回,会报警告,返回了一个堆上的地址,函数运行结束会被释放
  • 字符指针是一个左值,可以进行赋值
  • 字符数名是一个右值,表示一个数组,不允许被赋值

指针数组和数组指针

  • 指针数组是数组 int p[5] []的优先级高于 所以 p[5] 先结合成数组
  • 数组指针是指针 int (p)[5] ()使和p先结合成指针

原文地址