从CPU运作机理看指针本质
指针是C语言的灵魂,是万能的,也是鬼魅
CPU是通过三总线(地址总线、数据总线、控制总线)去访问RAM,ROM和外设寄存器的。
地址总线位宽决定了CPU寻址能力,比如说51单片机有16位地址总线,那么它的寻址能力是4KB,STM32是32位,寻址能力是4GB
CPU位宽:数据总线位宽决定了CPU一次能读写多少位数据
控制总线用来协调CPU与存储器、寄存器之间的读写
比如WR为低电平的时候,表明地址总线和数据总线的值有效,此时存储器会接收地址和数据,完成数据的写入操作。
单片机运行的核心原理
CPU通过总线来读写存储器,外设存储器,从而把程序跑起来,实现控制。
C语言中指针就是有类型的地址,地址就是地址总线上的地址码,而类型决定了从这个地址上读写数据的长度。
(uint8_t *)(0x12345678)是何意义?
0x12345678是一个32位常数,前面加上(uint8_t *)就变成了uint8_t类型的指针
*((uint8_t *)(0x12345678)) = 0x55;
以上是给0x12345678地址的uint8_t类型数据赋值为0x55
* 号在定义的时候是定义成指针,也是运算符,用来取出指针的地址码所对应的存储单元
赋值操作本质和指针滥用风险
uint8_t *p = (uint8_t *)(0x12345678);一般是把一些数据存在特定的地址,或者定义一些外设的寄存器。
一般正常用法:
typedef unsigned char uint8_t;
int main(void) {
uint8_t *p;
uint8_t array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
p = array;
*(p + 5) = 0x55;
return 0;
}
C语言中一切皆指针,因为一切程序最终实现,都是CPU的寻址操作
uint32_t a; 就是编译器开辟了一个4字节的连续内存,并且命名为a,本质就是&a,&就是取值运算符
指针变量本身占多少字节呢?
这与CPU地址总线宽度有关,51单片机,地址总线16位,那他的指针变量所占字节不少于2,STM32不少于4
多重指针:
uint8_t ****p = NULL;
指针分为指针变量和指针常量
一份正常的代码:
char *p = NULL;
char arr[] = "12345wer90";
for (p = arr; *p != '\0'; p++) {
printf("%c", *p);
}
那可不可以这样写:
char arr[] = "12345wer90"