C语言-指针_01

指针基础

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 = &num; 定义一个指针变量存储变量p的地址
int **p2;

注意:

如果在一行中定义多个指针变量,每个指针变量前面都需要加*来修饰
void fun05()
{
    int a,b,c;
    int *p1,*p2,*p3;
}

1.2 初始化

(1)、定义指针变量时,赋真实的地址

c 复制代码
int num = 10;
int *p = &num;

(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 = &num;
        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 = &num; 				//此时 * 表示 变量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)
...

例:

c 复制代码
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int num = 10;
    int *p = &num;			//去除变量名,剩余指针类型 int *,便于判断等号左右两边类型是否一致
    printf("p = %p\n", p);

    char *p2 = &num;		//语法错误,=两边类型不一致,但是编译器会做优化,只报警告,不报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 = &num;
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 = &num;
    printf("*p = %d\n", *p);    //*p = 16909060

    char *p2 = (char *)&num;    //强制转换为char *类型
    printf("*p2 = %d\n", *p2);  //*p2 = 4

    short *p3 = (short *)&num;  
    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 = &num;
    printf("*p1 = %d\n", *p1);
    printf("*p2 = %d\n", *p2);
    printf("*p3 = %d\n", *p3);

    void * p4 = &c;
    void * p5 = &s;
    void * p6 = &num;

    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 = &num;
    printf("*p=%d\n",*p);
    void *p2 = &num;
    printf("*p2=%d\n",*p2);
}

5.4 操作指针变量不要越界

c 复制代码
#include <stdio.h>

void fun04()
{
    int num = 0x01020304;
    int *p = &num;
    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也可以通过,会有警告,相当于指针变量赋给二维指针变量
相关推荐
懒大王爱吃狼21 分钟前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
秃头佛爷1 小时前
Python学习大纲总结及注意事项
开发语言·python·学习
待磨的钝刨1 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
XiaoLeisj3 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
励志成为嵌入式工程师4 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉5 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer5 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq5 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
记录成长java6 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
前端青山6 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js