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也可以通过,会有警告,相当于指针变量赋给二维指针变量
相关推荐
sp_wxf4 分钟前
Lambda表达式
开发语言·python
Fairy_sevenseven16 分钟前
【二十八】【QT开发应用】模拟WPS Tab
开发语言·qt·wps
蜡笔小新星24 分钟前
Python Kivy库学习路线
开发语言·网络·经验分享·python·学习
凯子坚持 c24 分钟前
C语言复习概要(三)
c语言·开发语言
无限大.36 分钟前
c语言200例 067
java·c语言·开发语言
余炜yw38 分钟前
【Java序列化器】Java 中常用序列化器的探索与实践
java·开发语言
无限大.38 分钟前
c语言实例
c语言·数据结构·算法
篝火悟者39 分钟前
问题-python-运行报错-SyntaxError: Non-UTF-8 code starting with ‘\xd5‘ in file 汉字编码问题
开发语言·python
Death20041 分钟前
Qt 中的 QListWidget、QTreeWidget 和 QTableWidget:简化的数据展示控件
c语言·开发语言·c++·qt·c#
六点半88843 分钟前
【C++】速通涉及 “vector” 的经典OJ编程题
开发语言·c++·算法·青少年编程·推荐算法