您的位置:首页 > 编程语言 > C语言/C++

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

2016-10-29 12:42 363 查看
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开辟内存

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言
相关文章推荐