C语言指针运算
一、算术运算
1,指针 ± 整数:这种形式只能用于指向数组中某个元素的指针;
int arr[5] = {1,2,3,4,5};
int *p1 = &arr[1];
printf("*(p1+2) = %d \n",*(p1+2));
printf("*(p1-1) = %d \n",*(p1-1));
输出结果:
*(p1+2) = 4
*(p1-1) = 1
2,指针 - 指针:此形式只能用于两个指针变量都指向同一个数组中的元素时才运行指针减指针,才有意义,结果是两个元素之间的位差;
int arr[5] = {1,2,3,4,5};
int *P1 = &arr[1];
int *P2 = &arr[4];
printf("P1 = %p\n",P1);
printf("p2 = %p\n",P2);
printf("P2 - P1 = %ld \n",P2 - P1);
输出结果:
P1 = 0x7ffc159de484
p2 = 0x7ffc159de490
P2 - P1 = 3
3,指针 ± 十六进制:指针一般是十六进制格式,再加减一个十六进制数,这种形式称为地址偏移,一般用于各个变量位置关系基本固定,有明确的首地址偏移量(偏移多少个字节),例如通过某个结构体首地址来操作该结构体某个成员变量,(一般不使用减法操作)
typedef struct
{
int a;
char b;
int c;
char d;
int e;
Testtype;
void main()
{
void *p = NULL;
Testtype stru = {3,'b',8,'D',10};
p = (void *)&stru; //void指针指向stru
printf("p->e = %d \n",((Testtype *)p)->e); //修改前,stru中e成员的值
*(int *)(p + 0x10) = 15; //通过指针偏移对e成员值进行修改
printf("p->e = %d \n",((Testtype *)p)->e); //修改后,stru中e成员的值
}
输出结果:
p->e = 10
p->e = 15
还有STM32库函数版本中用于外设寄存器寻址也是这种操作,例如串口外设基地址 = 外设所挂载的总线基地址 + 地址偏移量
#define USART2_BASE (APB1PERIPH_BASE + 0x4400)
二、关系运算
关系运算:可使用关系运算符“< ,<=,>,>=,==,!=”表示两指针之间的关系运算表示它们指向的地址位置之间的关系,指向地址大的指针大于指向地址小的指针。
STM32中外设通道地址和外设地址进行比较,来判断该通道属于哪个外设,再对外设进行初始化:
if((u32)DMA_Streamx > (u32)DMA2)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
}
else
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
}
不同数据类型的指针间关系运算没有意义,指向不同数据区域的数据的指针间关系运算也无意义。
指针与一般整数变量之间的关系运算没有意义,但可以和零进行等于或不等于的关系运算,判断指针是否为空。
#define NULL_PTR ((void*)0)
if(p == NULL_PTR)
{ ... }