C语言——指针

Posted Li-Yongjun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言——指针相关的知识,希望对你有一定的参考价值。

指针即地址

内存是用来存储数据的,它可以通过地址来访问,C语言具有访问地址的能力,所以 C语言具有直接访问内存的能力。
例如,如下代码,意思是向地址为 0x20000550 的内存中写入值 10。

*(uint8_t *)0x20000550 = 10;
printf("value = %d\\r\\n", *(uint8_t *)0x20000550);
value = 10

我们常说的指针是什么呢?

  • 是变量
  • 变量的值具有特殊意义,是个地址

继续示例:

*(uint8_t *)0x20000550 = 10;
printf("value = %d\\r\\n", *(uint8_t *)0x20000550);

uint8_t *p;
p = (uint8_t *)0x20000550;
printf("*p = %d\\r\\n", *p);

uint8_t a;
a = 15;
printf("a = %d\\r\\n", a);
value = 10
*p = 10
a = 15

定义了一个变量 p,这个 p 是什么类型呢?是 uint8_t * 类型。
它和下面的变量 a,有什么区别呢?没什么区别。
变量 p 和变量 a,都是变量;
变量 p 和变量 a,都用来存储一个数值。
变量 p 存储的这个数值,类型是 uint8_t * 类型;
变量 a 存储的这个数值,类型是 uint8_t 类型。

值的类型有什么用呢?用处就是,指导编译器(或程序员)如何使用这个值。
编译器发现一个值是 uint8_t 类型,就知道它能存储的数值是 0-255,可以用它来做加减乘除运算。
编译器发现一个值是 uint8_t * 类型,就知道它存储的应该是个地址,可以尝试从这个地址取个数据看看。
注意,这里只是指导程序员如何使用这个值,而程序员完全可以不听从。
例如,他完全可以把 uint8_t 也当成一个地址,也去从这个地址中取个数据看看。只不过,硬件上没有这个地址,读取时会出错。
再例如,程序员也可以把 uint8_t * 当成一个普通的数值来用,进行加减乘除,这也是完全可以的。
不过,不按照数据类型来操作数据,往往会造成错误,所以一般我们还是要尊重数据类型的。

函数传参

继续示例

*(uint8_t *)0x20000550 = 10;
printf("value = %d\\r\\n", *(uint8_t *)0x20000550);

uint8_t *p;
p = (uint8_t *)0x20000550;
printf("*p = %d\\r\\n", *p);

uint8_t a;
a = 15;
printf("a = %d\\r\\n", a);

func(a);
printf("a = %d\\r\\n", a);
void func(uint8_t a1)

	a1 = 50;

value = 10
*p = 10
a = 15
a = 15

C语言中,函数的参数传递机制是“值传递”。当主调函数调用被调函数时,系统会把实参的值赋给形参。
上面的例子含义就是,主调函数将 15 这个值传递给了 func() 函数的形参 a1,也就是说,func() 函数和主调函数唯一有联系的就是 15 这个值,func() 函数和变量 a 没有任何联系

函数形参为指针

*(uint8_t *)0x20000550 = 10;
printf("value = %d\\r\\n", *(uint8_t *)0x20000550);

uint8_t *p;
p = (uint8_t *)0x20000550;
printf("*p = %d\\r\\n", *p);

uint8_t a;
a = 15;
printf("a = %d\\r\\n", a);

func(a);
printf("a = %d\\r\\n", a);

func2(&a);
printf("a = %d\\r\\n", a);
void func(uint8_t a1)

	a1 = 50;


void func2(uint8_t *a2)

	*a2 = 50;


value = 10
*p = 10
a = 15
a = 15
a = 50

再看上面这个例子,func2() 为什么能够把主调函数中的变量 a 的值给更改呢?前面不是说,被调函数和 a 没有任何关系吗?
是的,被调函数和 a 确实没有任何关系。被掉函数之和传递给它的值有关系,这里传给 func2() 的值为 &a,这是一个什么值呢?这个值就是变量 a 所在内存的内存地址。func2() 可以把这个值当作一个地址,然后改写这个地址对应的内存的值,实际上它也是这么干的,把这个内存中的值改写成了 50。
所以,func2() 和主调函数中的 a 没有关系,但是传递给 func2() 的值和 a 有关系,这个值是 a 的地址,任何代码(函数也好、语句也好)拿到这个值,都可以通过这个值访问内存,进而改写内存。

以上是关于C语言——指针的主要内容,如果未能解决你的问题,请参考以下文章

c语言中的RETURN()返回值是啥意思?

C语言数组参数与指针参数

CUDA主函数

函数要返回两个值时,主函数的接收要怎么做

c语言函数能不能返回结构体

C语言使用回调函数模拟委托与反射