一、指针
1、指针的读写基本单元为字节,指针变量内存的是其所指向变量的地址(编号)。
指针定义方式
类型名 * 指针变量名;
(类型也包括自定义类型,例如:结构体变量,数组变量,指针变量)
此指针变量 存放的是 此类型名类型 的变量 的地址
char *pc = NULL;//存放char型变量的地址
int *pi = NULL;//存放int型变量的地址
short *ps = NULL;//存放shart型变量的地址
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
例如:
#include<stdio.h>
int main()
{
int a = 10;
int *p = &a;
printf("%p\n", p);
printf("%p\n", &a);
return 0;
}
输出结果为012FFBA0,就是变量a 的地址
指向不同类型变量的指针大小在32位平台上是4个字节,在64位平台上是8个字节,因为指针变量中存放的都是变量的地址,通常用16进制数表示。
例如:
#include<stdio.h>
int main()
{
int n = 10;
char *pc = (char*)&n;//pc接受的是char型的n的地址,n的地址不变,但char型的变量占1个字节,所以pc+1会是地址+1;
int * pi = &n;//pc接受的是int型的n的地址,n的地址不变,int型的变量占4个字节,所以pc+1会是地址+4;
printf("%p\n", &n);// 006FF938
printf("%p\n", pc );//006FF938
printf("%p\n", pc+1);//006FF939
printf("%p\n", pi);//006FF938
printf("%p\n", pi+1);//006FF93C
return 0;
}
指针的类型决定了指针向前或者向后走一步有多大距离。
#include<stdio.h>
int main()
{
int n = 0x11223344;
int *pi = &n;
char *pc = (char *)&n;
//*pc = 0x55;//输出结果是11223355,只是因为在此计算机中用的是小端编址,意思就是将数据中的低权位存放在低地址中,也就是变量n的首地址中存的是44。
//而且pc是char型,所以只能对其一个字节进行操作,即将44变为55
*pi = 0;//输出结果为0,pi是Int型,所以是对n的四个字节进行操作
printf("%0x\n", n);
return 0;
}
指针的类型决定了对指针解引用时有多大的权限(能操作几个字节)
#include<stdio.h>
#define N_VALUES 5
int main()
{
float values[N_VALUES];
float* vp;
for (vp = &values[0]; vp < &values[N_VALUES];)
{
*vp++ = 0;//将数组元素赋值0;
}
return 0;
}
允许指向数组元素的指针与指向数组的最后一个元素的后面的那个内存位置进行比较,但不允许与只想第一个元素之前的那个内存位置的指针进行比较,所以不建议用第二种赋值方法
1、for (vp = &values[N_VALUES]; vp > &avlues[0])
{
*--vp = 0;
}
2、 for (vp = &values[N_VALUES]; vp > &avlues[0];vp--)
{
*vp = 0;
}
、
#include<stdio.h>
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
printf("%p\n", arr);//0093FC28
printf("%p\n", &arr[0]);//0093FC28
return 0;
}
意味着数组名在此代表着数组的首地址,即数组首元素的首地址
int * p=arr;//此语句成立;
#include<stdio.h>
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);//在sizeof中,数组名代表整个数组。
for (int i = 0; i < sz; i++)
{
printf("arr[%d]=%d\n", i,arr[i]);
}
return 0;
}
通过下标访问数组元素
#include<stdio.h>
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);//在sizeof中,数组名代表整个数组。
for (int i = 0; i < sz; i++)
{
printf("arr[%d]=%d\n", i,*(p+i));
}
return 0;
}
int * p;
p=10;//将p中存放的地址改为10;
相当于int* p=10;
二级指针
指针变量中存放的是另一个指针变量的地址
例如:
int a=8;
int * p=&a;
int* *p1=p;//p1中存放的是p的地址;
指针数组
数组中放的是指针型变量
例如:int* arr3[5];//指针数组,指针变量的集合
数组指针
int (*a)[5];//数组指针,指向数组的指针
注:以 int a[10] 为例;
1、数组中最后一个元素的地址只允许访问,不允许写入;
2、int a[10];
int* p=&a[0];
int*q =&a[9];
&a[9]-&a[0]=9;//结果是两元素中间的元素个数
3、数组名在sizeof中单独被操作时,代表整个数组
4、int a[10];
&a=a;//其数值一样,但意义不一样,a代表首元素首地址,&a代表数组的首元素首地址。 * (&a)解引用整个数组,,*a解引用首元素。
5、sizeof(a)//40,a在sizeof中单独作用,代表整个数组
sizeof(a+1)//4,代表a[1]的地址大小,32位平台均为4
printf("%p\n",a);//首元素地址
printf("%p\n",a+1);//a[1]的地址
printf("%p\n",&a+1);//会跳过整个数组到下一个数组的首地址