运算规则
运算优先级
运算优先级决定了表达式不同符号的先后运算顺序。
比如12+2 * 3,这里的运算符 * 比+优先级更高,所以会先计算2*3的值,而不是先计算12+2。由此可见运算符优先级对表达计算的重要性。
自增、自减运算符有前置和后置两种,这两种运算优先级是不同的。
优先级排序:p1++ > * p2 = --p3 (后置 > 指针解引 = 前置 )
即后置的优先级最高,指针解引和前置的优先级相同!
不要看百度百科的!!!
运算符优先级参考链接:geeksforgeeks运算符优先级
结合性
为什么会出现结合性?
上面优先级把运算符分成了很多等级,但是也会出现相邻运算符是同级的问题,所以出现了结合性。就是表达式出现相邻的运算优先级相同该如何去结合计算。
左结合性:自左向右。 后置
a2/1:这里和/优先级相同,且是做结合性,所以先计算a*2,然后计算2/1。
右结合性:自右向左。 前置、指针解引
前置与后置
前置先加减,再赋值。
a = ++b; 等价于 b = b+1, a = b
后置先赋值,后加减。
a = b++; 等价于 a= b, b = b+1
前置、后置与指针之间的纠缠
前置与指针
*++p;
首先根据优先级前置和指针解引是同级的,然后根据结合性都是右结合性。
*++p等价于 *(++p)
代码:
#include <stdio.h>
int main() {
// *++p
int arr[] = {11, 2};
int *p = arr;
printf("p addr:%p\n", p);
*++p = 0; // *(++p) = 0; p+=1, *p = 0
printf("p addr:%p, *p num:%d, arr[0]:%d, arr[1]:%d \n", p, *p, arr[0], arr[1]);
return 0;
}
输出结果:
p p addr:0x16d2bf530
p addr:0x16d2bf534, *p num:0, arr[0]:11, arr[1]:0
++*p
首先根据优先级前置和指针解引是同级的,然后根据结合性都是右结合性。
++*p等价于 ++(*p)
代码1:
#include <stdio.h>
int main() {
// ++*p
int arr[] = {11, 2};
int *p = arr;
printf("p addr:%p\n", p);
++*p; // ++(*p)
printf("p addr:%p, *p num:%d, arr[0]:%d, arr[1]:%d \n", p, *p, arr[0], arr[1]);
return 0;
}
输出结果1:
p addr:0x16d46b530
p addr:0x16d46b530, *p num:12, arr[0]:12, arr[1]:2
代码2:
#include <stdio.h>
int main() {
// ++*p
int arr[] = {11, 2};
int *p = arr;
printf("p addr:%p\n", p);
++*p = 0; // ++(*p), *p = 0;
printf("p addr:%p, *p num:%d, arr[0]:%d, arr[1]:%d \n", p, *p, arr[0], arr[1]);
return 0;
}
输出结果2:
p addr:0x16b4d7530
p addr:0x16b4d7530, *p num:0, arr[0]:0, arr[1]:2
后置与指针
*p- -
后置运算符比指针解引优先级更高,注意先赋值
*p-- 等价于 *(p--),注意这里的*p的p是p--前的值
代码:
#include <stdio.h>
int main() {
// ++*p
int arr[] = {11, 2};
int *p = &arr[1];
printf("p addr:%p\n", p);
*p-- = 18; // *(p--) , *p = 18 // 这里存在坑,*p中的p是没有p--前的
printf("p addr:%p, *p num:%d, arr[0]:%d, arr[1]:%d \n", p, *p, arr[0], arr[1]);
return 0;
}
输出结果:
p addr:0x16f4d3534
p addr:0x16f4d3530, *p num:11, arr[0]:11, arr[1]:18
综合练习
上面这些如果你都搞懂了,下面来个绝杀。
输入汉字或者英文,实现反转输出。
注意点
1、我这里使用utf8编码,对应的汉字是三个字节。如果使用gbk 那么汉字对应两个字节
2、汉字的每个字节使用unchar表示,汉字每个字节编码大于128,所以使用无符号char
3、使用char类型存储汉字字节编码是因为char类型能把编码对应的字符输出出来。如果用整形数组去存汉字编码是没法输出编码对应的汉字字符的
代码
代码:
// #include <stdio.h>
// int main() {
// // 中文倒置
// unsigned char str[4];
// str[0] = 0xE6;
// str[1] = 0x88;
// str[2] = 0x91;
// str[3] = 0;
// printf("%s\n", str); // 我utf8汉字三个字节
// return 0;
// }
#include <stdio.h>
#include <string>
using namespace std;
void inversion(unsigned char *);
int main() {
// 中英文反转输出
unsigned char str[100];
scanf("%s", str);
inversion(str);
printf("%s\n",str);
return 0;
}
void inversion(unsigned char * str) {
int len = strlen((char *)str); // 强制转换类型,否则无法测长度,strlen测出会自动减去\0
unsigned char temp[100];
unsigned char * p1 = str; // 源数组指针
unsigned char * p2 = temp + len; // p在结尾0位置
*p2-- = 0; // *(p2--) *p2, p2--, *p2 = 0 这里的*p2 = 0中的p2并未移位
while(*p1) {
// 英文
if(*p1<0x80) { // <128. ascii字符0-127
*p2-- = *p1++;
} else {
*(p2-2) = *p1++;
*(p2-1) = *p1++;
*p2 = *p1++;
p2 -= 3;
}
}
p1 = str;
printf("%s\n", temp);
for(int i=0; i<len; i++) {
*(p1+i) = temp[i];
}
}
输入:
我n爱a
输出:
a爱n我