C语言指针
1.指针变量的定义和指针变量的基类型
定义指针变量一般形式如下:
类型名 *指针变量1,*指针变量2 …
例如:
int *pi, *pj;
在定义语句中,在每个变量前的星号*是一个说明符,用来说明变量是指针变量。
int是类型名,说明pi和pj是两个指向整型(int类型)变量的指针,只能存放int类型变量的地址。(指针变量pi和pj的基类型为Int)
以下定义的p为一个指向指针的指针类型
int **p, *s, k = 20
s = k; p = &s;
这里的指针变量p的基类型是基类型为int类型的指针类型。&为求地址运算符。
(基类型不同,存储字节大小不同,int类型4个字节,short int类型2个字节,这里涉及指针的移动,地址值增1减1跨越的字节数是不同的,故而要区分基类型)
2.给指针变量赋值
2.1给指针变量赋地址值
有三种方式,第一种通过求地址运算符&;第二种通过指针变量;第三种通过标准库函数。
第一种:
int k = 1, *q,*p;
q = &k;
这里注意&只能用于变量和数组元素,不能用于常量或者被register说明的变量和表达式。
第二种:
//续上
p = q;
这时候,指针变量q和p存储单元的内容都是k的地址啦。
赋值运算的时候,指针变量的基类型一定要相同。
第三种:
通过调用库函数malloc和calloc在内存中开辟动态存储单元,并把单元地址赋给指针变量。
2.2给指针变量赋空值
举例:
p = NULL; p = '\0'; p = 0;
以上三种等效,这时并不是指向地址为0的存储单元,而是具有确定的值”空“。
3.对指针变量操作
3.1 通过指针访问存储单元
举例:
int *p,i = 10,j;
p = &i;
j = *p;
星号*是间接访问运算符,可以直接通过 *来访问该地址存储单元。
*号右端是存放地址的指针变量,或者是地址。
3.2 移动指针
移动指针比较简单,注意"++"和”*“两个符号优先级相同,但运算顺序是自右向左。
3.3 指针比较
略。
4.函数之间地址值的传递
4.1 形参为指针变量时实参和形参之间的数据传递
4.2通过传送地址值在被调用函数中直接改变调用函数的值
4.1和4.2可以用一个例子:
void swap(int *a, int *b)
{
int t;
printf("(2)a = %d b = %d\n", *a, *b);
t = *a; *a = *b; *b = t;
printf("(3)a = %d b = %d\n",*a, *b);
}
int main()
{
int x = 30; y = 20;
printf("(1) x = %d y = %d\n",x,y);
swap(&x,&y);
printf("(4) x = %d y = %d\n"x,y);
}
程序流程,先打印x,y。然后实参x,y的地址传进形参a,b。再次打印a和b指向地址的存储单元的值,交换存储单元值后再次打印,出swap函数后再次打印。
4.3函数返回地址值
只不过是函数的返回类型为指针类型。
心得
写这篇文章的原因是因为学stm32单片机过程中,涉及直接在寄存器中写数据,而在寄存器中写数据本质就是改变相应地址的存储单元中的值。(用FSMC扩展SRAM和用FSMC驱液晶时候的问题)
所遇到的问题:
*(uint16_t *)(0x60020000) = 0xABCD;
本人的理解:先把0x6002000强制转换成基类型为unsigned int类型的指针变量,指针变量存放的当然是地址喽,那再来一个星号*(间址运算符),所得的就是0x60020000地址的存储单元的值。在上面语句中0x60020000地址的存储单元的值被赋值为0xABCD。
写到这里,不禁感觉自己棒棒哒。问题完美解决,再次巩固了c语言的基础。继续加油😊。