C语言指针基础

目录

内存地址

取变量地址

指针

指针的使用

指针参数


内存地址

  • CPU内存的访问   ------>   通过内存地址来读写内存数据
  1. 读数据:CPU与内存条硬件之间有个地址总线,读数据的时候CPU通过地址总线将要访问的内存地址告诉内存条,内存条回数据给CPU,这样CPU就能获取内存里面的数据
  2. 写数据:CPU通过地址总线将地址告诉内存条,内存将数据存进去
  • 对于CPU而言地址是唯一的读写内存的方式
  • 内存地址是一个整数
  • 应用程序使用的内存地址,其实不是真实的物理地址,而是操作系统映射好的虚拟的内存地址
  • 32位系统与64位系统,虚拟地址是不一样的,32位系统它的地址是由32位的二进制表示的,64为的虚拟地址是由64位的二进制数据表示的

取变量地址

  • C语言里面使用'&'来获取变量所在内存的地址
    // 取地址

    int a = 10;

    // 每一个变量都会有一个内存地址,

    // 我们怎么求的这个变量的内存地址呢?

    // 使用取地址符号&,地址的显示都是16进制的

    printf("0x%x\n", &a); // 获得这个变量的起始地址;

    // end
  • 32位程序内存地址是32位的,64位程序内存地址是64位的   ------>   和操作系统有关

指针

  • C语言里面存放内存地址数据的变量就是指针,对于32位程序,那么指针变量的存储空间是4个字节,对于64位程序,指针变量的存储空间是8个字节
  • 指针的实质   ------>   指针存放一个地址数据的变量,指针变量
  • 指针的定义   ------>   数据类型* 变量名称,表示这个变量存放的是所定义的数据类型的内存地址数据,也确定了指向内存的大小
  • 指针变量内存分配
  1. 指针变量定义在哪里,指针变量的内存就分配在哪里
  2. 比如是一个全局的指针变量,那么就将内存分配到我们的数据段,大小为4个字节(32Bit),如果指针变量定义为一个局部变量,那么指针变量的内存就分配到栈上
  • 指针变量就是4个字节(32位)的变量,用来存放内存地址
 // 32bit os

    int m = 0; // 申请了一个内存,名字为m, 类型为int, 4个字节;

    int* p = NULL;  // 申请了一个内存,名字为p, 4个字节,用来存放内存地址,而且有这个变量的大小信息, int,

    p = &m;

    // end

    // 任何一个指针变量,存放一个有效的内存地址,

    // 或者是你知道的一个有意义的数据;

    // NULL 0x0000000 地址,是操作系统禁止访问,空地址,空指针;

    printf("mem size = %d\n", sizeof(p));

    printf("mem size = %d\n", sizeof(int*));

    // end

指针的使用

  • 指针变量的初始化
  1. 如果指针变量暂时没有存放任何内存的地址的数据,那么一般我们会将它初始化为NULL, 例如int* p = NULL, NULL就是指针变量里面存放的是0
  2. 通过取地址符号获取变量的地址,然后赋值给指针变量;int a; int* p = &a
  3. 给指针变量存地址的时候一定要是有意义的地址,不能乱搞
  • 通过指针读数据
  1. 取得指针变量里面存放的内存地址的数据
  2. cpu使用这个地址去访问内存,然后得到数据, 这两步通过 (*指针变量)来操作
    // 使用指针来访问指针指向的内存的数据;

    double n = 7; // 8个字节

    //类型* 大小取决于这个类型

    double* ptr = &n; // ptr 4个字节,存放了n的起始地址;

    // 使用ptr来访问内存数据呢?内存的起始地址,大小

    // *号来表示,从当前指针变量存放的内存地址开始,到当前指针数据类型的大小结束(double, 8, int 4)

    // 使用指针,来访问我们的内存数据:

    // 指针来访问内存数据两大要素:

    // (1) 内存起始地址;

    // (2) 内存的大小,所占的字节数;(指针的类型决定), sizeof(数据类型)

    // 定义一个指针变量 类型*

    printf("%lf\n", *ptr);

    char* ch_ptr; // *ch_ptr 内存大小为sizeof(char)

    short* sh_ptr; // *sh_ptr 内存大小是sizeof(short)

    int* int_ptr; // *int_ptr 内存大小是sizeof(int)

    // 普通的指针,存放地址的4个字节而已;

    int* *int_ptr2; // *int_ptr2 内存大小sizeof(int*) 4个字节

    // end
  • 通过指针来写数据
  1. 取得指针变量里面存放的内存地址数据
  2. cpu使用这个地址,将数据写入到内存里面
  • 使用指针访问内存的时候,要确保指针变量里面存放的地址是哪个内存是使用指针的关键
  • 如果指针变量里面存放的地址是一个不可控的地址数据,那么操作系统会杀掉当前的进程,抛出非法错误,比如使用存放 NULL的内存地址数据的指针
    char ch = 40;
    ch_ptr = &ch;
    sh_ptr = 789; // 本身是4个字节可以存放4个字节允许的数据;

    // printf("%d\n", *sh_ptr); // 非法的异常, sh_ptr --> 789, 然后作为内存其实地址, 2个字节的内存大小;

    // 789是一个被OS保护的地址,
    // 存放内存地址而用;
    void* v_ptr = &ch; // ch变量的内存地址

    // printf(*v_ptr); // 编译错误,void类型,没有字节大小
    // end

指针参数

  • 指针作为函数参数:将一个内存地址传入,函数里面就能拿到这个内存地址,通过内存地址来访问变量的内存
  • 编写函数,交换两个变量的值,分析下,指针作为参数传递的全过程
    int lhs = 7;
    int rhs = 8;

    swap(&lhs, &rhs);

    printf("lhs = %d rhs = %d\n", lhs, rhs);

    // 把一块内存的起始地址传递过去;
    static void swap(int* a, int* b) {

        // *a = 7, *b = 8

       int temp = *a; // temp = 7;

       *a = *b;
       *b = temp;
    }

代码练习

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 把一块内存的起始地址传递过去;
static void swap(int* a, int* b) {
	// *a = 7, *b = 8
	int temp = *a; // temp = 7;
	*a = *b;
	*b = temp;
}

int main(int argc, char** argv) {
	// 取地址
	int a = 10;
	// 每一个变量都会有一个内存地址,
	// 我们怎么求的这个变量的内存地址呢?
	// 使用取地址符号&,地址的显示都是16进制的
	printf("0x%x\n", &a); // 获得这个变量的起始地址;
	// end

	// 指针
	// (1)指针是一个变量, 变量定义在哪里内存分配在哪里;
	// (2)指针是一个什么样的变量呢?是存放内存地址的变量;
	// (3)变量内存多大呢?内存地址有多大,32位OS-->(4个字节), 64位OS(8个字节)
	// (4)变量存放的是哪种数据类型的类型的地址;
	// 类型* 变量名称;
	// int* 变量int类型的变量内存地址;
	// char* 变量char类型变量内存地址;
	// void* 没有任何数据类型的,就是一个地址,没有变量的大小信息的;

	// 32bit os
	int m = 0; // 申请了一个内存,名字为m, 类型为int, 4个字节;
	int* p = NULL;  // 申请了一个内存,名字为p, 4个字节,用来存放内存地址,而且有这个变量的大小信息, int,
	p = &m;
	// end 
	// 任何一个指针变量,存放一个有效的内存地址,
	// 或者是你知道的一个有意义的数据;
	// NULL 0x0000000 地址,是操作系统禁止访问,空地址,空指针;
	printf("mem size = %d\n", sizeof(p));
	printf("mem size = %d\n", sizeof(int*));
	// end

	// 使用指针来访问指针指向的内存的数据;
	double n = 7; // 8个字节
	//类型* 大小取决于这个类型
	double* ptr = &n; // ptr 4个字节,存放了n的起始地址;

	// 使用ptr来访问内存数据呢?内存的起始地址,大小
	// *号来表示,从当前指针变量存放的内存地址开始,到当前指针数据类型的大小结束(double, 8, int 4)
	// 使用指针,来访问我们的内存数据:
	// 指针来访问内存数据两大要素:
	// (1) 内存起始地址;
	// (2) 内存的大小,所占的字节数;(指针的类型决定), sizeof(数据类型)
	// 定义一个指针变量 类型*
	printf("%lf\n", *ptr);

	char* ch_ptr; // *ch_ptr 内存大小为sizeof(char)
	short* sh_ptr; // *sh_ptr 内存大小是sizeof(short)
	int* int_ptr; // *int_ptr 内存大小是sizeof(int)
	// 普通的指针,存放地址的4个字节而已;
	int* *int_ptr2; // *int_ptr2 内存大小sizeof(int*) 4个字节
	// end 
	char ch = 40;
	ch_ptr = &ch;
	sh_ptr = 789; // 本身是4个字节可以存放4个字节允许的数据;
	// printf("%d\n", *sh_ptr); // 非法的异常, sh_ptr --> 789, 然后作为内存其实地址, 2个字节的内存大小;
	// 789是一个被OS保护的地址,
	// 存放内存地址而用;
	void* v_ptr = &ch; // ch变量的内存地址
	// printf(*v_ptr); // 编译错误,void类型,没有字节大小
	// end 

	int lhs = 7;
	int rhs = 8;
	swap(&lhs, &rhs);
	printf("lhs = %d rhs = %d\n", lhs, rhs);
	system("pause");
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C语言指针基础知识点: 1.指针的定义和初始化 指针是一个变量,其值为另一个变量的地址。定义指针变量时需要指定指针所指向的变量类型,然后使用*运算符来声明指针变量指针变量的初始化可以为其赋值为另一个变量的地址,也可以将其初始化为NULL。 2.指针的运算 指针可以进行加、减、自增、自减等运算。指针加上一个整数n时,指向的地址会增加n个存储单元的大小,减去一个整数n时,指向的地址会减少n个存储单元的大小。 3.指针的比较 指针可以进行相等、大于、小于等比较运算。当两个指针指向同一个变量时,它们相等;当两个指针指向同一数组中的不同元素时,它们可以进行大小比较。 4.指针的类型转换 指针可以进行类型转换,但需要注意转换后的指针类型必须与指向的变量类型相同,否则可能会导致程序出错。 5.指针和数组 数组名本身就是一个指针,指向数组的第一个元素。可以使用指针来访问数组中的元素,也可以将指针作为函数参数来传递数组。 以下是一个例子,演示了指针的定义、初始化、运算和比较: ```c #include <stdio.h> int main() { int a = 10; int *p = &a; // 定义指向整型变量a的指针p printf("a的值为:%d\n", a); // 输出:a的值为:10 printf("p指向的变量的值为:%d\n", *p); // 输出:p指向的变量的值为:10 printf("p的值为:%p\n", p); // 输出:p的值为:0x7ffeeb5f8a2c printf("p+1的值为:%p\n", p+1); // 输出:p+1的值为:0x7ffeeb5f8a30 printf("p的地址为:%p\n", &p); // 输出:p的地址为:0x7ffeeb5f8a28 printf("p和&a的比较结果为:%d\n", p == &a); // 输出:p和&a的比较结果为:1 return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值