同一优先级的运算符,运算次序由结合方向所决定。
简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符
注意:sizeof是运算符,不要与函数混淆。
二 结合方向
运算符的结合性:
C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如算术运算符的结合性是自左至右,即先左后右。如有表达式 x-y+z则 y 应先与“-”号结合,执行 x-y 运算,然后再执行+z 的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。 最典型的右结合性运算符是赋值运算符。如 x=y=z,由于“=”的右结合性,应先执行 y=z 再执行 x=(y=z)运算。C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。
x << 1 得到的结果是左移1位后的值,它被保存在一个临时变量中,与x无关,即x的值不变。
x <<= 1 相当于 x = x << 1,是将x左移1位以后的值保存回x中,x发生了变化。
GPIOE->ODR|=1<<5; 怎么理解呢?
1、先把1看做十六进制,0x01即0000 0001,1<<5,0x01左移5位变为,0x20即0010 0000
2、再进行 | 或运算,0x20与GPIOE->ODR进行或运算,就是对第五位进行置1,其它位不变。
3、赋值=,把刚刚或运算后的值,赋值给GPIOE->ODR
C语言中*(volatile unsigned int *)0x500的解释:
如下;
(unsigned int *)0x500:将地址0x500强制转化为int型指针,注意现在是指针类型,所以它必须有数据类型,0x500只是地址值。
可以访问sizeof(unsigned int)长的字节数据。
*(unsigned int *)0x500=0x10:对地址为0x500赋值为0x10
使用一个32位处理器,要对一个32位的内存地址进行访问,可以利用宏定义这样定义
#define RAM_ADDR (*(volatile unsigned long *)0x0000555F)//先强制转换为unsigned int类型指针,然后再通过*访问。
然后就可以用C语言对这个内存地址进行读写操作了
读:tmp = RAM_ADDR;//tmp=*(0x0000555F)
写:RAM_ADDR = 0x55;
volatile 易变的
volatile是一个类型限定符,如const一样
volatile变量可变允许除了程序之外的比如硬件来修改他的内容
变量如果加了 volatile 修饰,则会从内存重新装载内容,而不是直接从寄存器拷贝内容。
访问该数据任何时候都会直接访问该地址处内容,即通过cache提高访问速度的优化被取消
对于((volatile unsigned long ) 0xE0028000)为随硬件需要定义的一种地址,前面加上“”指针,为直接指向该地址,整个定义约定符号IOPIN代替,调用的时候直接对指向的地址寄存器写内容既可。这实际上就是内存映射机制的方便性了。其中volatile关键字是嵌入式系统开发的一个重要特点。上述表达式拆开来分析,首先(volatile unsigned long *) 0xE0028000的意思是把0xE0028000强制转换成volatile unsigned long类型的指针,暂记为p,那么就是#define A *p,即A为P指针指向位置的内容了。这里就是通过内存寻址访问到寄存器A,可以读/写操作
一篇不错的文章
C语言再学习 -- 关键字volatile
https://blog.csdn.net/qq_29350001/article/details/54024070
地址的定义
文章
https://www.cnblogs.com/wp2312139418/p/5869181.html
设置GPIOB_0输出为高电平 #define GPIOB 0x40010C00 #define GPIOx_ODR 0x0c #define GPIOB_ODR *((volatile unsigned int *)(GPIOB + GPIOx_ODR)) //重点是这里的意思,先把GPIOB_ODR地址计算出来,再转换为 unsigned int类型指针 ,那么就可以通过指针GPIOB_ODR访问地址为0x40010C00+0x0c里面的4个字节的值了。 (unsigned int 的大小跟操作系统有关,如果是STM32的话,就是32位的,占四个字节,寄存器不正好32位的吗,所以才强制转换为unsigned int) GPIOB_ODR |= 1 << 0;//1左移0位,也是1,赋值给0x40010C0c地址开始的四个字节 即0x40010C0c的四个字节的值为0x00000001
stm32 寄存器组起始地址