a和&a的区别以及数组和指针的用法

a和&a的区别:


<pre name="code" class="cpp">#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main()
{
   int a[5] = {1,2,3,4,5};
   int *ptr = (int *)(&a + 1);
   printf("%d %d",*(a + 1),*(ptr - 1));
    system("pause");
    return 0;
}

 结果如下: 

a表示的是数组首元素的首地址,而a+1表示下一个元素的地址,再给这个地址解引用,
表示取这个地址里面存放的内容,而这个地址里面存放的是2这个元素,所以*(a+1)
的值为2;
&a表示的是数组的首地址,&a+1表示的是下一个数组的首地址,就是说ptr里面存
放的是下一个数组的首地址,ptr为一个指针变量,这个指针变量-1就等于前一个元素的地址,
(1的单位是元素的个数,而不是给指针变量的值减1)
即就是a[4]的地址,再给这个地址解引用就等于a[4]这个元素,即就是5

指针和数组的对比:

指针p:
1)保存数据的地址,任何存入指针变量p里的值都会被当做地址来处理,
并且有些书上是这样讲的,指针就是地址,乍一听会觉得说的很对,
但是还不够精确,正确的应该这样来理解,指针在作为右值时是一个地址。
在说一下左值和右值的区别,左值是指一个地址空间,而右值是一个地址里存放的内容。
而p本身的地址存储在哪里,我们并不知道。
 2)间接访问数据,首先取出这个指针变量存放的地址,然后读取这个地
址里存放的内容,或者向这个地址里存放数据,指针可以以指针的形式
访问*(p+i),也可以通过下标的形式来访问p[i];(这里的i的单位也是
元素的个数。),不论是以指针的形式还是以下标的形式,其实质都是
先取出p里面的内容(另一个变量的地址),然后通过这个地址,访问
这个地址所存放的内容。
数组:
1)保存同种类型数据的一个集合,数组名代表的是数组首元素的首地址,同理,a本身的地址
我们并不知道,并没有一个保存a本身地址的变量。
2)直接访问数据,数组名a是整个数组的名字,数组内的元素没有名字,不能把数组
当做一个整体来访问,数组可以以指针的形式访问*(a+i),也可以通过下标的形式
来访问a[i].(注意:i的单位是元素的个数),其实质是用a代表的数组首元素的首地址
加上i*sizeof(数组元素的类型),然后,读取这个地址的内容。

指针数组和数组指针:

指针数组(储存指针的数组):
  首先它是一个数组,数组里面存放元素都是指针
例如:
int  *p1[ 10]; 
“[ ] ”的优先级高于“*”,所以p1先和10结合,p1[10]是一个数组,而
int *修饰的是数组的内容,表示数组里面存放的每个元素都是 int *类型
数组指针(指向数组的指针)
首先它是一个指针,这个指针指向一个数组,这个指针里面存放的是一个数组
的首地址。(而不是数组首元素的首地址)
例如:
int (*p2) [10] ; 
"( )"的优先级高于"[ ]",*和p2构成了一个指针的概念,指针变量名为p2,
这个指针指向的数组没有数组名,这个数组里面存放的每个元素都是int类型的。

例如:

p3和p4都是指向整个数组的, p3 赋值号两边的数据类型一致,都是指向数组的首地址
p4赋值号两边的数据类型不一致,赋值号左边的p4指向数组的首地址, 而右边的a代表
数组首元素的首地址,两边的类型不一致,但是可以编译成功,是因为a和&a作为右值时,
只是取它们的值,而它们虽然表示的意义不一样,但是值是一样的,所以可以编译通过,但是一般不要这样使用。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include"windows.h"
int main()
{
   char a[5] = {'A','B','C','D'};
   char (*p3)[5] = &a;
   char (*p4)[5] = a;
    printf("%p\n",p3);
   printf("%p\n",p3+1);
    printf("%p\n",p4);
   printf("%p\n",p4+1);
    system("pause");
    return 0;
}

结果如下:



#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include"windows.h"
int main()
{
   char a[5] = {'A','B','C','D'};
   char (*p3)[3] = &a;
   char (*p4)[3] = a;
    printf("%p\n",p3);
   printf("%p\n",p3+1);
    printf("%p\n",p4);
   printf("%p\n",p4+1);
    system("pause");
    return 0;
}



结果如下:结果可以看出p3和p4加1时地址的变化是和p3以及p4指向的数组的大小有关,

而与给它赋值的数组大小没有关系





#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include"windows.h"
int main()
{
   char a[5] = {'A','B','C','D'};
   char (*p3)[10] = &a;
   char (*p4)[10] = a;
    printf("%p\n",p3);
   printf("%p\n",p3+1);
    printf("%p\n",p4);
   printf("%p\n",p4+1);
    system("pause");
    return 0;
}

结果如下:




无法把指针变量本身传递给一个函数,在c语言中,当一维数组作为函数参数
的时候,编译器总是把它解析为一个指向其首元素首地址的指针,但是注意,
只有一维数组才是如此,当数组超过一维时,将第一维改写为指向数组首元素
首地址的指针之后,后面的维不可改写

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void GetMemory(char *p,int num)
{
   p = (char *)malloc(num *sizeof(char));
}
int main()
{
   char *str = NULL;
   GetMemory(str, 10);
   strcpy(str, "hello");
   free(str);//free并??没?有?D起e到??作???用??,??内??存??泄1漏?
   system("pause");
   return 0;
}


运行时发生错误,p分配的内存并没有传递给str ,而是传递给了str的一份拷贝,假设这个拷贝名为 _str,而这个_str是编译器自动分配和回收的,我们根本无法使用

如果想要获取一块内存,可以这样做:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * GetMemory(char *p,int num)
{
   p = (char *)malloc(num *sizeof(char));
   return p;
}
int main()
{
   char *str = NULL;
   str = GetMemory(str, 10);
   strcpy(str, "hello");
   printf("%s",str);
   free(str);
   system("pause");
   return 0;
}



结果如下:




#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void GetMemory(char **p,int num)
{
   *p = (char *)malloc(num *sizeof(char));
}
int main()
{
   char *str = NULL;
    GetMemory(&str, 10);
   strcpy(str, "hello everyone");
   printf("%s",str);
   free(str);
   system("pause");
   return 0;
}

结果如下:可以看出,*p 就是 str,所以给*p开辟内存空间,就等于给str开辟内存























  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值