指针基础
1. 概述
**地址编号:**计算机为了存储数据,每一个程序在 32位 机中 占4G,
最小操作单位是一个字节,每一个字节都有其对应的地址,该地址就是地址编号。**指针:**地址编号这个数据 的 数据类型。
**指针变量:**存储地址编号的 变量,其 数据类型为 指针。
注意:
在32位平台下, 地址总线是32位的, 所以地址是32位编号, 所以指针变量是32位的, 即4个字节。 在64位平台下, 地址总线是64位的, 所以地址是64位编号, 所以指针变量是64位的, 即8个字节。代码:
c#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型数据的地址编号的数据类型 双精度浮点型指针 ...如:
c//案例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)、定义指针变量时,赋真实的地址
            
            
              c
              
              
            
          
          int num = 10;
int *p = #(2)、当指针变量的值 等于 NULL 时,这种指针叫做 空指针
            
            
              c
              
              
            
          
          int *p = NULL;(3)、当指针变量是局部变量,在其定义时没有赋值,此时系统将随机给其一个值,这种指针称为 野指针
            
            
              c
              
              
            
          
          int *p;1.3 运算符
1.3.1 &
- 
作用:取地址 
- 
& 取地址符 可取区域:只能获取变量地址栈区 静态全局区 

- 
代码: c#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 *
作用:取值 或 改值(修改指针指向的地址的值)
语法:*指针变量名
            
            
              c
              
              
            
          
          #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 = 203. 指针类型
3.1 指针本身的类型
指针变量 去除 变量名,剩余的就是 指针本身的类型
如:
int *p1;	// int *  
int **p2;	//int **
int (*p)(int int);//int (*)(int,int)
...例:
            
            
              c
              
              
            
          
          #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 取值宽度
            
            
              c
              
              
            
          
          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字节例:
            
            
              c
              
              
            
          
          #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 *, 这种指针被称为万能指针,意味着任何一种地址都可以赋值给该类型的指针变量
例:
            
            
              c
              
              
            
          
          #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 野指针操作会出现段错误
            
            
              c
              
              
            
          
          void fun01()
{
    //野指针
    int *p;
    printf("*p=%d\n",*p);
}
5.2 空指针操作会出现段错误
            
            
              c
              
              
            
          
          void fun02()
{
    //空指针
    int *p = NULL;
    printf("*p=%d\n",*p);
}
5.3 不要对万能指针进行操作
            
            
              c
              
              
            
          
          void fun03()
{
    int num = 10;
    int *p = #
    printf("*p=%d\n",*p);
    void *p2 = #
    printf("*p2=%d\n",*p2);
}
5.4 操作指针变量不要越界
            
            
              c
              
              
            
          
          #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
// 0x20304616. 练习
案例1:以下赋值语句正确的是___
int num=10, *p=&num, **q=&p;
A:p=&num B:q =p; c:q=&num D:q=&p;
正确答案:AD
但是,Bc也可以通过,会有警告,相当于指针变量赋给二维指针变量
