指针基础
1. 概述
地址编号:计算机为了存储数据,每一个程序在 32位 机中 占4G,
最小操作单位
是一个字节
,每一个字节都有其对应的地址,该地址就是地址编号
。指针:地址编号这个数据 的 数据类型。
指针变量:存储地址编号的 变量,其 数据类型为 指针。
注意:
在32位平台下, 地址总线是32位的, 所以地址是32位编号, 所以指针变量是32位的, 即4个字节。 在64位平台下, 地址总线是64位的, 所以地址是64位编号, 所以指针变量是64位的, 即8个字节。
代码:
#include <stdio.h> int main(int argc, char const *argv[]) {printf("char * 大小为:%ld\n",sizeof(char *));printf("short * 大小为:%ld\n",sizeof(short *));printf("int * 大小为:%ld\n",sizeof(int *));printf("long * 大小为:%ld\n",sizeof(long *));printf("float * 大小为:%ld\n",sizeof(float *));printf("double * 大小为:%ld\n",sizeof(double *));return 0; }
输出:
char * 大小为:8 short * 大小为:8 int * 大小为:8 long * 大小为:8 float * 大小为:8 double * 大小为:8
2. 指针变量
1.1 定义
语法:
数据类型 变量名
指针的类型:
char * 存储字符型数据的地址编号的数据类型 字符指针 short * 存储short型数据的地址编号的数据类型 短整形指针 int * 存储int型数据的地址编号的数据类型 整形指针 long * 存储long型数据的地址编号的数据类型 长整形指针 float * 存储float型数据的地址编号的数据类型 单精度浮点型指针 double * 存储double型数据的地址编号的数据类型 双精度浮点型指针 ...
如:
//案例1: int num = 10; 定义一个指针变量存储num的地址 int *p; //案例2: char c = 'a'; 定义一个指针变量存储c的地址 char *p //案例3: int *p = # 定义一个指针变量存储变量p的地址 int **p2;
注意:
如果在一行中定义多个指针变量,每个指针变量前面都需要加*来修饰 void fun05() {int a,b,c;int *p1,*p2,*p3; }
1.2 初始化
(1)、定义指针变量时,赋真实的地址
int num = 10;
int *p = #
(2)、当指针变量的值 等于 NULL
时,这种指针叫做 空指针
int *p = NULL;
(3)、当指针变量是局部变量,在其定义时没有赋值,此时系统将随机给其一个值
,这种指针称为 野指针
int *p;
1.3 运算符
1.3.1 &
-
作用:取地址
-
& 取地址符
可取区域
:只能获取变量地址栈区
静态全局区
-
代码:
#include <stdio.h> char c = 'a'; int main(int argc, char const *argv[]) {int num = 10;int *p = #printf("p = %p\n", p);char *p2 = &c;printf("p2 = %p\n", p2);// int *p3 = &10; //& 取常量10的地址会报错const int num02 = 20;int *p4 = &num02;printf("p4 = %p\n", p4);return 0; }// 输出: // p = 0x7ffe8dfe59f8 // p2 = 0x601040 // p4 = 0x7ffe8dfe59fc
1.3.2 *
作用:取值 或 改值(修改指针指向的地址的值)
语法:*指针变量名
#include <stdio.h>
int main(int argc, char const *argv[])
{int num = 10;int *p = # //此时 * 表示 变量p是int型指针变量printf("*p = %d\n", *p); //此时 * 表示为取值*p = 20;printf("num = %d\n", num);return 0;
}// 输出:
// *p = 10
// num = 20
3. 指针类型
3.1 指针本身的类型
指针变量 去除 变量名,剩余的就是 指针本身的类型
如:
int *p1; // int *
int **p2; //int **
int (*p)(int int);//int (*)(int,int)
...
例:
#include <stdio.h>
int main(int argc, char const *argv[])
{int num = 10;int *p = # //去除变量名,剩余指针类型 int *,便于判断等号左右两边类型是否一致printf("p = %p\n", p);char *p2 = # //语法错误,=两边类型不一致,但是编译器会做优化,只报警告,不报errorprintf("p2 = %p\n", p2);return 0;
}
3.2 指针指向的数据的数据类型
指针变量 去除 变量名与最近的一个,剩余的就是
指针
指向的数据的 类型如:
int *p1; // int int **p2; // int * int (*p)(int int); //int (int int) ...
3.3 取值宽度
int num = 0x01020304;
int *p = #
print("*p = %d\n", *p);
问题:num为int型变量,占4个字节,那就是4个地址(1个字节,一个地址),
那么指针变量p在存储num的地址时,是怎么存储的?存储的是哪个地址?
答:指针变量有取值宽度,如下:
指针变量的数据类型 决定了 取值宽度:
int * 取值宽度为4字节
char * 取值宽度为1字节
short * 取值宽度为2字节
...
例:与单位跨度同一代码
3.4 单位跨度
指针变量的数据类型 决定了 单位跨度:(就是地址在进行加减时地址增减的字节数)
int * 单位跨度为4字节
char * 单位跨度为1字节
short * 单位跨度为2字节
例:
#include <stdio.h>int main(int argc, char const *argv[])
{int num = 0x01020304;//对应的十六进制:0x0000 0001 0000 0010 0000 0011 0000 0100//Linux系统存储是倒叙存储的://0000 0100 0000 0011 0000 0010 0000 0001//0x04 0x03 0x02 0x01int *p = #printf("*p = %d\n", *p); //*p = 16909060char *p2 = (char *)# //强制转换为char *类型printf("*p2 = %d\n", *p2); //*p2 = 4short *p3 = (short *)# printf("*p3 = %d\n", *p3); //*p3 = 772 对应的十六进制:0x0304printf("*p2 = %d\n", *(p2+1)); //*p2 = 3 对应的十六进制:0x03 此时p2为首个字节存储的地址+1,加的是一个单位跨度即1字节printf("*p2 = %d\n", *(p2+2)); //*p2 = 2 对应的十六进制:0x02 步长为1,+2表示向后挪二位printf("*p3 = %d\n", *(p3+1)); //*p3 = 258 对应的十六进制:0x0102 步长为2,+1表示向后挪二位return 0;
}
4. void
作用:
1、当函数没有返回值时,返回值类型为void;
2、void和指针结合作为一种指针类型,如
void *
, 这种指针被称为万能指针
,意味着任何一种地址
都可以赋值
给该类型的指针变量
例:
#include <stdio.h>
int main(int argc, char const *argv[])
{char c = 'a';short s = 1;int num = 10;char * p1 = &c;short * p2 = &s;int * p3 = #printf("*p1 = %d\n", *p1);printf("*p2 = %d\n", *p2);printf("*p3 = %d\n", *p3);void * p4 = &c;void * p5 = &s;void * p6 = #return 0;
}
5. 指针变量使用的注意事项
5.1 野指针操作会出现段错误
void fun01()
{//野指针int *p;printf("*p=%d\n",*p);
}
5.2 空指针操作会出现段错误
void fun02()
{//空指针int *p = NULL;printf("*p=%d\n",*p);
}
5.3 不要对万能指针进行操作
void fun03()
{int num = 10;int *p = #printf("*p=%d\n",*p);void *p2 = #printf("*p2=%d\n",*p2);
}
5.4 操作指针变量不要越界
#include <stdio.h>void fun04()
{int num = 0x01020304;int *p = #char *p2 = (char *) p;printf("%#p\n",*p2);printf("%#p\n",*(p2+1));char c = 'a';char * p3 = &c;//1int *p4 = (int *)p3;printf("%#p\n",*p4);
}int main(int argc, char const *argv[])
{fun04();return 0;
}// 输出:
// 0x4
// 0x3
// 0x2030461
6. 练习
案例1:以下赋值语句正确的是___
int num=10, *p=&num, **q=&p;
A:p=&num B:q =p; c:q=&num D:q=&p;正确答案:AD
但是,Bc也可以通过,会有警告,相当于指针变量赋给二维指针变量