指针基础
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 = # //语法错误,=两边类型不一致,但是编译器会做优化,只报警告,不报error
printf("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 0x01
int *p = #
printf("*p = %d\n", *p); //*p = 16909060
char *p2 = (char *)# //强制转换为char *类型
printf("*p2 = %d\n", *p2); //*p2 = 4
short *p3 = (short *)#
printf("*p3 = %d\n", *p3); //*p3 = 772 对应的十六进制:0x0304
printf("*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;
//1
int *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也可以通过,会有警告,相当于指针变量赋给二维指针变量