C语言符号之初章


在这里插入图片描述

🌈反斜杠 \

🌳续行符

  • 代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	if (1 == a && 2 == b && 3 == c)
	{
		printf("you can see me\n");
	}
	return 0;
}

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	if (1 == a && \
		2 == b && \
		3 == c)
	{
		printf("you can see me\n");
	}
	return 0;
}

在这里插入图片描述

  • 作用

👉续行符就是为了续行。如果一行代码太长,我就可以换到下一行去写。
👉 在用户看来:新起了几行。
在编译器看来:仍然是一行。

  • 注意

👻在换行符之后不要出现任何符号,包括空格在内。也就是\之后直接回车

  • 疑问

Q:有人说不用 \ 直接换行也行?就像这样

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	if (1 == a && 
		2 == b && 
		3 == c)
	{
		printf("you can see me\n");
	}
	return 0;
}

答:这个问题就好像你不加返回值(编译器就会默认返回值为int)代码照样能够运行一样。你直接换行的话,当别人看你代码时,他会产生疑惑:你是写错了,还是刻意这样。所以你加上\,就是告诉他:我这里就是嫌代码长,需要换行方便阅读。

🌳转义字符

🍁字面转特殊

  • 代码
int main()
{
	printf("hello n world");
	return 0;
}

在这里插入图片描述

int main()
{
	printf("hello \n world");
	return 0;
}

在这里插入图片描述

👉 对比两者,可以知道 字面值 n --> 转义字符 \n.这就是字面转特殊

🍁特殊转字面

  • 代码
int main()
{
	printf("\"");
	return 0;
}

在这里插入图片描述

👉功能为打印双引号。双引号作为字符串分隔符本身就看作特殊字符。我们加上\来获得字面意思。

🌳回车和换行符

  • 基本概念

👉回车是指光标回到当前位置的最开始。

👉换行是指光标移至下一行

🤟 它们两者是不一样的概念。

  • 有趣的代码

1.旋转光标(VS下)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
int main()
{
	char* str = "/-|\\";//这里为了打印\,在\之前又加了\以获得字面值
	int num = 0;
	while (1)
	{
		num %= 4;//4次算一个周期
		printf("%c\r", str[num]);
		Sleep(300);//每次打印暂停300毫秒
		num++;
	}
	return 0;
}

在这里插入图片描述

2.倒计时

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
int main() {
	int i = 10;
	while (i--)
	{
		printf("[%2d]\r", i);
		Sleep(300);
	}
	printf("\n");
	return 0;
}

在这里插入图片描述

🌈 单引号和双引号

  • 代码
    在这里插入图片描述
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
//int main()
int main()
{
	printf("%d\n", sizeof(1));//4
	printf("%d\n", sizeof("1"));//2
	printf("%d\n",sizeof(""));//1
	
	printf("%d\n", sizeof('1'));//4  为啥不是1?
	char c = '1';
	printf("%d\n", sizeof(c));//1
	
	return 0;
}

在这里插入图片描述

🪐 在C99中,像 '1’整形字符常量,它会被编译器看成整形。
🛰️所以 char a = ‘1’;会发生截断。4字节数据会写入到1字节空间去。

🌈逻辑运算符和位运算符

🌳逻辑运算符

  • &&

🚀级联两个(多个)逻辑表达式,必须同时为真,结果才为真


🚀什么是级联?
答:多个对象之间的映射关系

  • ||

🚀级联两个(多个)逻辑表达式,必须至少一个为真,结果才为真

  • 短路

Q:什么是短路
答:上面的一个条件不满足,已经不需要在看后续的条件的情况,
就叫做短路

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
int show()
{
	printf("you can see me\n");
	return 1;
}
int main()
{
	int a = 0;
	scanf("%d", &a);
	10 == a && show();
	return 0;
}

在这里插入图片描述
在这里插入图片描述

📡 对于&&短路,从左向右看,只要有一个结果不为真,后面就不用看了!最后结果就是假。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
int show()
{
	printf("you can see me\n");
	return 1;
}
int main()
{
	int a = 0;
	scanf("%d", &a);
	10 == a || show();
	return 0;
}

在这里插入图片描述
在这里插入图片描述

📡对于||短路,从左向右看,只要有一个结果为真,那么后面也不用看了!整体结果就是真。

🌳位运算符

  • &

☘️二进制位遇0则为0。
在这里插入图片描述
在这里插入图片描述

  • |

☘️二进制位遇1则为1。
在这里插入图片描述
在这里插入图片描述

  • ^

☘️二进制位相同为0,相异为1。

在这里插入图片描述
在这里插入图片描述

☘️技巧

a^a = 0
a^0 = a

☘️支持交换律和结合律

这里是引用
在这里插入图片描述

🌳&&和&区别

☘️ &&:级联的是多个逻辑表达式,需要的是真假结果
☘️& :级联的是多个数据,逐比特位进行位运算
☘️逻辑结果:吃了吗?
☘️数据结果:吃了多少?

🌳交换两个数(不使用第三变量)

  • 方法一:
int main()
{
	int a = 10;
	int b = 20;
	a = a + b;//a == 30 ,b == 20
	b = a - b;//30-20 == 10
	a = a - b;//30-10 == 20
	return 0;
}

🍃当数据很大就会有栈溢出问题。
为啥呢?
因为溢出的本质就是比特位增多,而加法就可能导致进位,使得比特位增多
比如 10 + 90,它们都是两位数。
结果为 100(三位数)

  • 方法二
int main()
{
	int a = 10;
	int b = 20;
	printf("before:a = %d,b = %d\n", a, b);
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("after:a = %d,b = %d\n", a, b);
	return 0;
}

在这里插入图片描述

🍃这样写就避免了栈溢出的问题。
因为 ^ 不会产生进位。

  • 补充

🍃溢出(进位)其实都会被记录在寄存器的比特位当中。当你写回内存时,才会发生第二个问题。也就是截断(内存空间不足)!

🌳两个测试代码

  • demo1:

🍂位操作需要用宏定义好后再使用(推荐)

  • 代码一(将指定比特位设置为1)
#define SETBIT(x,n) ((x)|= (1<<(n-1)))//将指定比特位设置为1
//打印32个比特位
void ShowBits(int x)
{
	int num = sizeof(int) * 8 - 1;//31
	while (num >= 0)
	{
		if (x & (1 << num))
		{
			printf("1");
		}
		else
		{
			printf("0");
		}
		num--;
	}
	printf("\n");
}
int main()
{
	int x = 0;
	printf("before");
	ShowBits(x);
	SETBIT(x, 2);
	printf("after:");
	ShowBits(x);
	return 0;
}

在这里插入图片描述

  • 代码二(将指定比特位设置为0)
#define CLRBIT(x,n) ((x)&=~(1<<(n-1)))//将指定比特位设置为0
//打印所有比特位
void ShowBits(int x)
{
	int num = sizeof(int) * 8 - 1;//31
	while (num >= 0)
	{
		if (x & (1 << num))
		{
			printf("1");
		}
		else
		{
			printf("0");
		}
		num--;
	}
	printf("\n");
}
int main()
{
	int x = -1;
	printf("before");
	ShowBits(x);
	CLRBIT(x, 2);
	printf("after:");
	ShowBits(x);
	return 0;
}

在这里插入图片描述

🌳一个整形提升问题

int main()
{
	char c = 0;
	printf("sizeof(c): %d\n", sizeof(c)); //1
	printf("sizeof(c): %d\n", sizeof(~c)); //4
	printf("sizeof(c): %d\n", sizeof(c << 1)); //4
	printf("sizeof(c): %d\n", sizeof(c >> 1)); //4
	return 0;
}

🍂无论任何位运算符,目标都是要计算机进行计算的,而计算机中只有CPU具有运算能力(先这样简单理解),但计算的数据,
都在内存中。故,计算之前(无论任何运算),都必须将数据从内存拿到CPU中,拿到CPU哪里呢?毫无疑问,在CPU 寄存器
中。
而寄存器本身,随着计算机位数的不同,寄存器的位数也不同。一般,在32位下,寄存器的位数是32位。
可是,你的char类型数据,只有8比特位。读到寄存器中,只能填补低8位,那么高24位呢?
就需要进行“整形提升”。
🍂也就是说像c<<1这样的表达式结果是 int类型。发生了整型提升!
🍂sizeof(!c)在VS中的结果为1,但在Linux中结果为4。

🌈 左移和右移

🌳基本概念

👻<<(左移): 最高位丢弃,最低位补零
👻>>(右移):
1. 无符号数:最低位丢弃,最高位补零[逻辑右移]
2. 有符号数:最低位丢弃,最高位补符号位[算术右移]

🌳代码

  • demo1
int main()
{
	//左移
	unsigned int a = 1;//二进制位:0000 0000 0000 0000 0000 0000 0000 0001 -->1
	printf("%u\n", a << 1);//      0000 0000 0000 0000 0000 0000 0000 0010 -->2
	printf("%u\n", a << 2);//      0000 0000 0000 0000 0000 0000 0000 0100 -->4
	printf("%u\n", a << 3);//      0000 0000 0000 0000 0000 0000 0000 1000 -->8
	//逻辑右移
	unsigned int b = 100;// 二进制位:0000 0000 0000 0000 0000 0000 0110 0100-->100
	printf("%d\n", b >> 1);//         0000 0000 0000 0000 0000 0000 0011 0010-->50
	printf("%u\n", b >> 2);//         0000 0000 0000 0000 0000 0001 0001 1001-->25
	printf("%u\n", b >> 3);//         0000 0000 0000 0000 0000 0011 0000 1100-->12
	//算术右移,最高位补符号位1, 虽然移出了最低位1,但是补得还是1
	int c = -1;//二进制位:           1111 1111 1111 1111 1111 1111 1111 1111
	printf("%d\n", c >> 1);//         1111 1111 1111 1111 1111 1111 1111 1111
	printf("%d\n", c >> 2);//         1111 1111 1111 1111 1111 1111 1111 1111
	printf("%d\n", c >> 3);//         1111 1111 1111 1111 1111 1111 1111 1111

	return 0;
}
  • demo2
int main()
{
	//是算术右移,还是逻辑右移?最高位补0,为何?
	unsigned int d = -1;
	printf("%d\n", d >> 1);
	printf("%d\n", d >> 2);
	printf("%d\n", d >> 3);
	return 0;
}

👻那是补0还是补1呢?
答:补0.因为判定依据:看自身类型,和变量的内容无关。在这里插入图片描述
在这里插入图片描述

🌈 结尾

今天就分享到这,希望对你有帮助😊😊😊

在这里插入图片描述

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值