学习数组与指针

来源:互联网 发布:oracle数据库难学吗 编辑:程序博客网 时间:2024/06/08 02:03

首先什么是指针
一般我们知道int *p;表示定义了一个整型的指针变量,其空间大小是4byte,空间名字是p,同时限定这 4 个字节的空间里面只能存储某个内存地址,即使你存入别的任何数据,都将被当作地址处理,而且这个内存地址开始的连续 4 个字节上只能存储某个 int类型的数据。
p是一个指针变量,p里所存储的内存地址处的内存称为p所指向的内存,
同时在 32 位系统下,不管什么样的指针类型,其大小都为 4byte。
void *p
这里在类型与变量中间的*号,此时表达的含义类似声明的作用。
eg:
int *p=NULL 与 *p=NULL有什么区别?
这时候我们可以通过监视查看 p 的值为 0x00000000。这句代码的意思是:定义一个指针变量 p,其指向内存里面保存的是 int 类型的数据;在定义变量 p 的同时把 p 的值设置为0x00000000,而不是把*p 的值设置为 0x00000000。这个过程叫做初始化,是在编译的时候进行的。
在做一个实验:
int i=10;
int *p=&i;
*p=NULL;
在编译器上调试一下,我们发现 p 指向的内存由原来的 10 变为 0 了;而 p 本身的值, 即内存地址并没有改变。
经过上面的分析,已经明白它们之间的区别了。

接下来我们再看数组
int ar[10];//这里我们开辟10个相邻的整型的空间。
首先有个疑问这里10换成其他的变量可以吗?
我们知道这两个下标符号中间的值必须是整型值且为正数(旧标准),不能为空。
下标中可以放如:

#define ARRAYSIZE 10const int a=10;//以上两种可以放在数组的下标中,直接用宏定义或者被const的修饰的变量int ar[7/2];//满足结果是正整数int ar2[5%2];int ar3[sizeof(int)];int ar4['a'];//填写字符也可以,其是以ASC码存储//以上也是可以保证这个值在编译期间,编译器能知道能找到。

数组的初始化
int ar[]={1,2}; int ar2[]={1,2,}也可以但不能是int ar3[]={,,2,3};

int ar[10]={};
数组的首地址与指针

当在函数中定义一个数组时,sizeof(数组名)表示整个数组的字节大小如:int ar[10];//sizeof(ar)=40。但是当该数组名作为实参传递到其他函数中时,在函数内在sizeof(数组名)就不在是整个数组的字节大小,而是指针变量的空间大小4字节。还有对于++等的运用,数组名不可++,但退化成指针可以++。在一个函数中定义的一个数组,当对数组名使用&时,也表示取整个数组的地址而不是首元素的地址,(虽然两个的值是一样的但是意义不同)。

例题:

void main(){    int a[5]={1,2,3,4,5};    int *ptr=(int *)(&a+1);    int *ptr2=(int *)((int)a+1);    printf ("%d,%d,%x,%x",*(a+1),*(ptr-1),ptr1[-1],*ptr2);}

试问打印的值是多少?
2,5,5,2000000(小端) 不知道你对了没

首先对指针进行加 1 操作,得到的是下一个元素的地址,而不是原有地址值直接加 1。所以对为 一个类型为 T的指针的移动,以 sizeof(T) 为移动单位。 因此,对上题来说,a 是一个1维数组,数组中有 5 个元素; ptr 是一个 int 型的指针。

&a + 1: 取数组 a 的首地址,该地址的值 再加上 sizeof(a) (此时sizeof(a)就是整个数组的字节大小)的值,即 &a +5*sizeof(int),也就是下一个数组的首地址,显然当前指针已经越过了数组的界限。

(int*)(&a+1): 则是把上一步计算出来的地址,强制转换为 int* 类型,赋值给 ptr *

*(a+1): a,&a 的值是一样的,但意思不一样,a 是数组首元素的首地址,也就是 a[0]的首地址,&a 是数组的首地址,a+1 是数组下一元素的首地址,即 a[1]的首地址,&a+1 是下一个数组的首地址。所以输出 2
*(ptr-1): 因为 ptr 是指向 a[5],并且 ptr 是 int 类型,所以 *(ptr-1) 是指向 a[4] ,而ptr[-1]实际上就是*(ptr-1),输出 5。

(int)a+1 的值是元素 a[0]的第二个字节的地址。然后把这个地址
强制转换成 int*类型的值赋给 ptr2,也就是说*ptr2 的值应该为元素 a[0]的第二个字节开始的连续 4 个 byte 的内容。那么这4个byte里到底存了什么?看看监视
由于楼主系统是小端模式,不用判断大小端,当不知道时此处是有两个答案哦!
由于内存显示我们可以清晰的知道我们的ptr2的地址是从0x0019ff11这里到0x0019ff14,由于是小端模式高位在下,所存的数应该02000000但是输出时系统去掉前面无用的0,所以显示(以%x)2000000。
当然大端模式下是100。

以指针形式访问和以下标形式访问:
以指针的形式:*(a+4)。a 这时候代表的是数组首元素的首地址,假设为 0x0000FF00,然后加上 4 个字符的偏移量,得到新的地址0x0000FF04。然后取出 0x0000FF04 地址上的值。

以下标的形式:a[4]。编译器总是把以下标的形式的操作解析为以指针的形式的操作。a[4]这个操作会被解析成:a 作为数组首元素的首地址,然后加上中括号中 4 个元素的偏移量,计算出新的地址,然后从新的地址中取出值。
也就是说:
int ar[10]
int i;
//i[ar]=>*(i+ar)
//ar[i]=>*(ar+i)
int *p=ar;
//*(p+1)=>p[1]
这些在编译器看来都是指针形式使用

两者关系:
指针就是指针,指针变量在 32 位系统下,永远占 4 个 byte,其值为某一个内存的地址。
指针可以指向任何地方,但是不是任何地方你都能通过这个指针变量访问到。
数组就是数组,其大小与元素的类型和个数有关。定义数组时必须指定其元素的类型和个数。数组可以存任何类型的数据,但不能存函数。

原创粉丝点击