指针和数组的分析

前言:

数组是一段连续的内存空间,数组的空间大小为sizeof(array_type)array_size,数组名可看做指向数组第一个元素的常量指针* ,指针是一种特殊的变量,与整数的运算规则为p+n等价于(unsigned int)p+n*sizeof(*p),指针之间只支持减法运算,参与减法运算的指针类型必须相同,即p1-p2等于((unsigned int)p1 - (unsigned int)p2)/sizeof(type),特别注意的是只有当两个指针指向同一个数组的元素时,指针的相减才有意义,指针也可以进行关系运算(<,<=,>,>=),但是对于比较运算(==,!=)的指针类型必须相同

深入分析

1.数组名不等同于指针
test.c

#include <stdio.h>
int main()
{
   extern int a[];
   printf("&a = %p\n",&a);
   printf("a  = %p\n",a);
   printf("*a = %d\n",*a);
   return 0;
}

ext.c

int a[]={1,2,3,4,5};

结果:

&a = 0x804a014
a  = 0x804a014
*a = 1

将extern int a[]改为extern int *a
结果:

&a = 0x804a014
a  = 1
段错误 (核心已转储)

通过运行结果可以知道数组名只不过在某些情况下面可以看作指针,但是数组名绝对不是指针,当声明为extern int a[]时,a就标志着数组的起始地址,当声明为extern int *a时&a表示指针a的起始地址在数组的起始地址,但是a里面保存的地址就是数组的首元素1(四个字节),所以1地址是非法访问的空间就会出现段错误,特别说明的是a和&a是有区别的,&a为整个数组的地址,a为数组首元素的地址,区别在于指针运算,a+1等同于(unsigned int)a+sizeof(a),&a+1等同于(unsigned int)(&a)+sizeof(a),(unsigned int)(&a)+sizeof(&a)
2 面试题分析

int main()
{
  int a[5] = {1,2,3,4,5};
  int *p1 = (int*)(&a+1);
  int *p2 = (int*)((int)a+1);
  int *p3 = (int*)(a+1);
  printf("%d,%d,%d\n",p1[-1],p2[0],p3[1]);
  return 0;
}

结果

5,33554432,3

在这里插入图片描述
我们可以知道&a+1就是移动一个数组的长度,p1指向a[6],p1[-1]就相当于往前移动一个指针的位置即p1指向a[5],所以第一个打印出来是5,a里面保存的是数组的首地址,转化为int类型后加一就指向了0x804a015,而且Linux是小端系统,所以*p2的值就为0x02000000,十进制为33554432,对于p3来说很显然就为3
数组参数
数组作为函数参数时,编译器将其编译成对应的指针,所以在一般情况下,当定义的函数中有数组参数时,需要
定义另一个参数标识数组的大小

void f(int a[])<->void f(int *a);
void f(int a[5])<->void f(int *a);

test.c

#include <stdio.h>

void func1(char a[5])
{
    printf("In func1: sizeof(a) = %d\n", sizeof(a));
    
    *a = 'a';
    
    a = NULL;
}

void func2(char b[])
{
    printf("In func2: sizeof(b) = %d\n", sizeof(b));
    
    *b = 'b';
    
    b = NULL;
}

int main()
{
    char array[10] = {0};
    
    func1(array);
    
    printf("array[0] = %c\n", array[0]);
    
    func2(array);
    
    printf("array[0] = %c\n", array[0]);
    
    return 0;
}

结果:

In func1: sizeof(a) = 4
array[0] = a
In func2: sizeof(b) = 4
array[0] = b
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值