指针和++、--的纠缠

运算规则

运算优先级

运算优先级决定了表达式不同符号的先后运算顺序
比如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我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

划水猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值