数组和指针的区别

发现好多人搞不清楚数组和指针的区别。

数组申明时编译器自动分配一片连续的内存空间

指针申明时只分配了用于容纳指针的4字节空间

作为函数参数时,数组参数和指针参数等价

数组名在多数情况下可视为常量指针,其值不能改变

指针的本质是变量,保存的值被看做内存中的地址。

名字上的区别:

数组名通常情况下被作为常量指针,只能作为左值出现,
对于数组 
  1. int a[5];  
  2. a和&的意义不同,a是数组元素的首地址,&a是整个数组的地址  
int a[5];
a和&的意义不同,a是数组元素的首地址,&a是整个数组的地址
看下面程序
  1. #include <stdio.h>  
  2.   
  3.   
  4. int main()  
  5. {  
  6.     int a[5] = {1,2,3,4,5};  
  7.     int *p1 = (int *)(&a + 1);  
  8.     int *p2 = (int *)(a + 1);  
  9.     printf("p1[-1] = %d\n",p1[-1]);<span style="white-space: pre;">         </span>//5  
  10.     printf("p2[-1] = %d\n",p2[-1]);<span style="white-space: pre;">         </span>//1  
  11. }  
#include <stdio.h>


int main()
{
	int a[5] = {1,2,3,4,5};
	int *p1 = (int *)(&a + 1);
	int *p2 = (int *)(a + 1);
	printf("p1[-1] = %d\n",p1[-1]);			//5
	printf("p2[-1] = %d\n",p2[-1]);			//1
}
复制上的区别:
前面说了数组名一般只能作为左值出现,所以复值的时候只能一个一个来,而指针,则可直接进行
  1. <span style="white-space: pre;">    </span>int a1[5] = {1,2,3,4,5};  
  2.     int a2[5];  
  3.     a2 = a1;    //oOps  
  4.     for(int i = 0;i < 5;i++)  
  5.     {  
  6.         a2[i] = a1[i];      //*a2++ == *a1++  
  7.     }  
  8.     char *p1 = "hello";  
  9.     char *p2 = NULL;  
  10.     p2 = p1;                //正确,p2也指向了hello所在内存空间   
	int a1[5] = {1,2,3,4,5};
	int a2[5];
	a2 = a1;	//oOps
	for(int i = 0;i < 5;i++)
	{
		a2[i] = a1[i];		//*a2++ == *a1++
	}
	char *p1 = "hello";
	char *p2 = NULL;
	p2 = p1;				//正确,p2也指向了hello所在内存空间 

计算内存空间大小的区别:
计算数组所占内存大小使用sizeof这个关键字,而计算字符串使用 size_t strlen(const char *s);函数,这里是好多人常出现错误的地方,不少人计算数组长度喜欢用strlen看下面例子
  1. <span style="white-space: pre;">    </span>char s1[] = {'a','\0','c','c'};  
  2.     int s2[] = {0,1,2,3,4,5,6,7,8};  
  3.     printf("%d\n",strlen(s1));  
  4.     printf("%d\n",strlen(s2));  
	char s1[] = {'a','\0','c','c'};
	int s2[] = {0,1,2,3,4,5,6,7,8};
	printf("%d\n",strlen(s1));
	printf("%d\n",strlen(s2));
上面两个均不能的到正确结果,究其原因还得探究 size_t strlen(const char *s) ;的实现。
  1. size_t strlen(const char *str)  
  2. {  
  3.     int len = 0;  
  4.        assert(str != NULL);  
  5.        while(*str != '\0')  
  6.        {  
  7.               len++;  
  8.        }  
  9.        return len;  
  10. }  
size_t strlen(const char *str)
{
    int len = 0;
       assert(str != NULL);
       while(*str != '\0')
       {
              len++;
       }
       return len;
}

看了原型大家都知道上面的结果是怎么来的了。再次强调求数组所占内存空间用sizeof关键字。
字符串数组和字符数组:
  1.   char s1[] = {'h','e','l','l','o'};  
  2. char s2[] = "hello";  
  3. printf("%d\n",sizeof(s1));  
  4. printf("%d\n",sizeof(s2));<span style="white-space: pre;">      </span>//printf("%d\n",strlen(s2));结果是6  
   char s1[] = {'h','e','l','l','o'};
	char s2[] = "hello";
	printf("%d\n",sizeof(s1));
	printf("%d\n",sizeof(s2));		//printf("%d\n",strlen(s2));结果是6

结果分别是4和5,在C中并没有字符串数据类型,只是用字符数组进行模拟,在最后以‘\0’结束;
字符串数组和字符串:
  1.    char s1[] = "hello";  
  2. char *s2 = "hello";  
  3. s1[1] = 'H';          
  4. s2[1] = 'H';    //oOps  
    char s1[] = "hello";
	char *s2 = "hello";
	s1[1] = 'H';		
	s2[1] = 'H';	//oOps

这里主要是有个存储位置的问题。s2指向的一个字符串字面量,存在在只读代码段,其值不能被修改,s1是字符串数组存在栈空间。
作为形参传递:
数组名作为形参传递的时候是有退化的
  1. void fun(int a[5]) <==> void fun(int a[]) <==>  void fun(int *a)  
void fun(int a[5]) <==> void fun(int a[]) <==>	void fun(int *a)

所以在传递数组的时候还需要另一个参数,指示数组大小。其他情况
  1. void fun(int *a[5]) <==> void fun(int *a[]) <==>    void fun(int **a)  
  2.      void fun(int a[5][6]) <==> void fun(int a[][6]) <==>   void fun(int (*a)[6])  
void fun(int *a[5]) <==> void fun(int *a[]) <==>	void fun(int **a)
     void fun(int a[5][6]) <==> void fun(int a[][6]) <==>	void fun(int (*a)[6])
三维或更多维数组无法使用
定义数组使用为指针,定义为指针,使用为数组:
定义为数组使用为指针:
  1. //b.c  
  2. #include <stdio.h>  
  3. char str[] = "hello";  
  4. //a.c  
  5. #include <stdio.h>  
  6.   
  7. extern char *str;  
  8. int main()  
  9. {     
  10.     printf("%s",str);   //oOps,正解printf("%s",(char *)&str);  
  11.     return 0;  
  12. }  
//b.c
#include <stdio.h>
char str[] = "hello";
//a.c
#include <stdio.h>

extern char *str;
int main()
{	
	printf("%s",str);   //oOps,正解printf("%s",(char *)&str);
	return 0;
}
定义为指针使用为数组
  1. //b.c  
  2. #include <stdio.h>  
  3.   
  4. char *str = "hello";  
  5.   
  6. //a.c  
  7.   
  8. #include <stdio.h>  
  9.   
  10. extern char str[];  
  11. int main()  
  12. {     
  13.     printf("%s",str);//输出什么?正解:printf("%s",(char *)(*(unsigned int *)str));  
  14.     return 0;  
  15. }  
//b.c
#include <stdio.h>

char *str = "hello";

//a.c

#include <stdio.h>

extern char str[];
int main()
{	
	printf("%s",str);//输出什么?正解:printf("%s",(char *)(*(unsigned int *)str));
	return 0;
}
这两个的形成原因是由于对数组和指针的处理方式不同(指针是间接的,数组是直接的)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值