C语言深度剖析 -- 深度理解符号

news2024/9/21 20:31:16

文章目录

    • 注释符号
      • y=x/*p
      • 条件编译
    • 续行符与转义符 \
      • 回车与换行的区别
    • 单引号与双引号
    • 逻辑运算符
    • 位运算符
      • &、|、^
      • 整型提升问题
      • 左移 << 右移 >>
      • 花括号(了解,不太推荐)
      • ++、-- 操作符

我们为什么要深入理解C语言中的符号呢?符号有什么好说的呀?符号就像我们写代码中的桥梁,没有符号,我们是不可以从桥的一端通向另一端的!C语言中的符号本身不多,也就二十几个。
在这里插入图片描述

注释符号

写注释使我们代码的一个好的优点,注释我们需要简而精,注释要做到:简单、一动,不存在二义性,简单的代码不需要加上注释;

C语言的注释有两种,一种是 /* */、一种是 //

#include <stdio.h>

int main()
{
	int /*   */ i = 10;//正确
	char* s = "abcdef   //ghigk";//正确
	//Is it a\
	valid comment?     //正确,反斜杠\表示续航符
	in/* */t j = 20;//错误
	return 0;
}

注意1:注释本质是被替换成空格的
例如:

在这里插入图片描述
这种写法就是正确的,我们从而也可以知道# 与 define之间是可以带空格的;

注意2:c风格的注释是无法嵌套的

在这里插入图片描述
这样编译器会报错,/* 总会与离他最近的 */匹配

y=x/*p

我们本意是要拿x除以指向p里面的值,我们测试一下

	int x = 10;
	int y = 0;
	int z = 5;
	int* p = &z;
	y = x / * p;
	printf("%d\n", y);

如果我们要写成y = x /* p;这样编译器是会把 /* 识别成注释的;这种情况我们应写成y = x / * p;或者y = x/(*p);;
/与*之间没有空格,编译器就会把/*认为成是注释的开始

条件编译

我们都知道,有些软件会分为会员和非会员,而非会员的部分功能是无法使用的,那么在设计程序时,我们需要写两部分吗?肯定是不需要的,我们只需要将那些会员功能给隐藏就可以了;这里就会用到条件编译,当达到某些条件时,才会执行这些代码!
例如:

#include <stdio.h>

int main()
{
//条件编译
#if 0 //0就是不执行,非0就是执行
	printf("for test1\n");
	printf("for test2\n");
#endif

	//基于条件编译,我们还可以这样写,但是不推荐这样写
	if (0)
	{
		printf("for test1\n");
		printf("for test2\n");
	}
	return 0;
}

续行符与转义符 \

//1.\作为续行符
	int a = 1;
	int b = 2;
	int c = 3;
	if (a == 1 && \
		b == 2 && \
		c == 3) {
		printf("hello world\n");
	}

	//2.\作为转义符
	printf("h\tello wor\nld!\n");

在这里插入图片描述
这里:\t 相当于 table键;\n表示换行

注意:\作为续行符时,后面不可以加空格,否则会报错,前面可以有空格

回车与换行的区别

回车(\r)是将光标移动到该行的开始,换行(\n)就是将光标移动到下一行; 回车加上换行才是我们理解上的回车(键盘上的enter键)
在这里插入图片描述
我们可以实现一个倒计时:

#include <stdio.h>
#include <Windows.h>

int main()
{
	int i = 10;
	while (i >= 0)
	{
		Sleep(1000);
		printf("%2d\r", i--);// \r表示回车,移动到该行的最开始
	}
	return 0;
}

单引号与双引号

单引号表示字符,而双引号表示字符串

printf("%d\n", sizeof(1));//4
printf("%d\n", sizeof('1'));//4
printf("%d\n", sizeof("1"));//2,要加上字符串结束标志
char c = '1';
printf("%d\n", sizeof(c));//1

C99标准的规定,'a’叫做整形常量字符,被看成int型,所以sizeof(‘1’)是4个字节大小,而char类型是占用一个字节的空间;char c = 'abcd'; printf("%c\n", c);//d所以这样的代码是正确的,但是单引号里面最多有四个字符,因为’ '看成int型,我们在最开始就说过先开辟好空间,再把变量存放进去,所以高位abc就被舍弃了,字符c里面只存储了一个字符d!

特殊情况:

printf("%d\n", sizeof(''));//报错
printf("%d\n", sizeof(""));//1,只有一个字符串结束标志\0

逻辑运算符

  1. &&:逻辑与,有假则假
  2. ||:逻辑或,有真则真

这里面的基础语法就不说了,我么只要知道逻辑运算符具有短路的运算规则;就是有一个条件不满足时,后面的条件就不再看了;

demo:

#include <stdio.h>

int show()
{
	printf("you can see me!\n");
	return 1;
}

int main()
{
	int a = 0;
	scanf("%d", &a);
	a == 10 && show();//当输入的a值不是10时,后面的show函数自动不执行
	return 0;
}

位运算符

&、|、^

按位与(&)、按位或(|)、按位异或(^)都是逐比特位进行位运算的!
我们主要来理解一下按位异或;

按位异或:逐比特位比较,相同为0,相异为1

按位异或满足交换律与结合律;例如:看一个现象

	printf("%d\n", 5 ^ 4 ^ 5);//4
	printf("%d\n", 5 ^ 5 ^ 4);//4
	printf("%d\n", 5 ^ (5 ^ 4));//4

根据按位异或满足交换律与结合律,我们可以通过这个规律来实现两个数交换(不使用中间变量)

#include <stdio.h>

int main()
{
	//方法1:有整形溢出的风险
	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);

	//方法2:按位异或
	a = 10, b = 20;
	printf("before: a = %d, b = %d\n", a, b);
	a ^= b;
	b ^= a;
	a ^= b;
	printf("after: a = %d, b = %d\n", a, b);
	return 0;
}

在这里插入图片描述
位操作,指定位修改比特位,我们用宏来定义;

#include <stdio.h>

#define SETBIT(x, n) ((x) |= (1 << (n - 1))) //指定比特位为1,用按位或
#define CLRBIT(x, n) ((x) &= (~(1 << (n - 1)))) //指定比特位为0,用按位与(要加上取反符号)

//输出数字的二进制
void ShowBit(int x)
{
	int num = sizeof(x) * 8 - 1;
	while (num >= 0)
	{
		if (x & (1 << num)) printf("1 ");
		else printf("0 ");
		num--;
	}
	puts("");
}

int main()
{
	int x = 0;
	//1.设置指定比特位为1
	SETBIT(x, 5);
	ShowBit(x);
	//2.设置指定比特位为0
	int y = 0xFFFF;
	CLRBIT(y, 5);
	ShowBit(y);
	return 0;
}

整型提升问题

先看现象:

	char c = 0;
	printf("%d\n", sizeof(c));//1
	printf("%d\n", sizeof(~c));//4
	printf("%d\n", sizeof(c << 1));//4
	printf("%d\n", sizeof(c >> 1));//4

无论什么运算符,都是需要计算机运算的,而计算机只有CPU具有运算能力;但数据都是在内存当中,所以计算之前都必须要从内存中拿取数据放到CPU中(CPU中的寄存器中);一般寄存器的位数都是32位,而一个char类型只占一个字符,需要整型提升!!!
但是,有一个特例,在vs中:printf("%d\n", sizeof(!c));//1只占一个字节,但在Linux中却占用四个字节,编译器有自己的理解;

左移 << 右移 >>

  1. 无符号数:最低位舍弃,最高位补0(逻辑左移右移)
  2. 有符号数:最低位舍弃,最高位补符号位(算数左移右移)

注意:0x01 << 2 + 3是多少?

	printf("%d\n", 0x01 << 2 + 3);//32
	printf("%d\n", 0x01 << (2 + 3));//32
	printf("%d\n", (0x01 << 2) + 3);//7

+的优先级比<<高

花括号(了解,不太推荐)

在这里插入图片描述

++、-- 操作符

以++为例:基础语法我们都了解,a++是先使用后++,++a是先++后使用;
如果是b = ++a;是先++在使用(赋值给b),但是如果是直接++a;呢,那怎么先使用呢?其实,不管会不会有值来接受这个值,我们都是将a放到寄存器中来+1操作,我们来看一下汇编代码:

在这里插入图片描述
总结:a++完整的含义是先使用,在自增;如果没有变量接收,那么直接自增,就是读取进寄存器,就没有然后了

来看一个例子:

	int i = 1;
	int j = (++i) + (++i) + (++i);
	printf("%d\n", j);

上面的答案应该是多少呢?C语言与gcc的答案还不太一样,++i是先自增在使用,gcc中先计算前面两个++i,也就是i先自增为2,然后第二个i再自增为3,i这时候在使用都是3,3 + 3 = 6,最后一个i在先自增,为4,在与前两个相加,也就是 3 + 3 + 4 = 10;C语言中,是三个++i同时先自增,最后i变成4,然后 4 + 4 + 4 = 12;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1369679.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JS入门笔记整理:函数

函数一般用来实现某种重复使用的功能&#xff0c;在需要使用该功能的时候&#xff0c;直接调用函数就可以了&#xff0c;不需要再重复地编写一大堆代码。并且在需要修改该函数功能的时候&#xff0c;也只需要修改和维护这一个函数就行。函数一般会在两种情况下使用&#xff1a;…

助力企业出海,Ogcloud提供一站式网络解决方案

随着全球市场的开放和跨境电商的蓬勃发展&#xff0c;越来越多企业开始在海外拓展业务。但在这过程中&#xff0c;各种各样的网络问题成为企业出海的阻碍。Ogcloud凭借其卓越的技术实力和丰富的经验&#xff0c;为全球业务的公司提供全面的网络解决方案&#xff0c;包括SD-WAN、…

文件或目录损坏的磁盘修复方法

文件或目录损坏是一种常见的计算机问题&#xff0c;可能由多种原因导致&#xff0c;如磁盘故障、病毒或恶意软件攻击、文件系统错误等。这些损坏可能导致数据丢失或无法访问文件&#xff0c;因此及时修复至关重要。本文将深入探讨文件或目录损坏的原因&#xff0c;并提供相应的…

Zookeeper的基础介绍和安装教程

1、 Zookeeper入门 1.1 概述 Zookeeper是一个开源的分布式的&#xff0c;为分布式应用提供协调服务的Apache项目。 1.2 特点 1.3 数据结构 1.4 应用场景 提供的服务包括&#xff1a;统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡等。 统一…

编程基础 - 初识Linux

编程基础 - 初识Linux 返回序言及专栏目录 文章目录 编程基础 - 初识Linux前言一、Linux发展简介二、现代Linux三、Linux系统各发行版小结 前言 为什么要学习Linux呢&#xff1f;我这Windows用得好好的&#xff0c;简单易用傻瓜式、用的人还超多&#xff01;但是我要告诉你的…

解决word图片格式错乱、回车图片不跟着换行的问题

解决word图片格式错乱、回车图片不跟着换行的问题 1.解决方法。 先设置为嵌入型 但是设置的话会出现下面的问题。图片显示不全。 进一步设置对应的行间距&#xff0c;原先设置的是固定值&#xff0c;需要改为1.5倍行距的形式&#xff0c;也就是说不能设置成固定值就可以。

mybatisplus快速入门-个人理解版

mybatisplus快速入门 1.快速入门1.1准备开发环境-idea2019.2.1版第一步&#xff1a;新建工程第二步&#xff1a;导入依赖 1.2创建数据库和表创建库表添加数据 1.3编写代码进行测试第一步&#xff1a;配置application.yml第二步&#xff1a;添加实体类第三步&#xff1a;添加map…

让开发改bug全靠催?分享6个实用技巧

测试小伙伴们&#xff0c;你们有遇到下图的情况吗&#xff1f; ​ 这张图其实还算“温柔”的&#xff0c;其实有些情况下&#xff0c;某些测试人员或者开发人员脾气大的可能撕逼或者快干架。所以如何和开发有效沟通&#xff0c;并高效劝说开发改掉bug是一门学问&#xff0c;以…

手拉手springboot3整合mybatis-plus多数据源

环境介绍 技术栈 springbootmybatis-plusmysql 软件 版本 mysql 8 IDEA IntelliJ IDEA 2022.2.1 JDK 17 Spring Boot 3.1.7 dynamic-datasource 3.6.1 mybatis-plus 3.5.3.2 加入依赖 <dependency><groupId>com.baomidou</groupId><arti…

softmax详解

在神经网络中&#xff0c;Softmax 是一个用于多类别分类的激活函数。给定一个包含原始分数&#xff08;未经处理的模型输出&#xff09;的向量&#xff0c;Softmax 将这些分数转化为表示概率分布的向量。具体而言&#xff0c;对于给定的原始分数向量 ( z )&#xff0c;Softmax …

STM32-03-STM32HAL库

文章目录 STM32HAL库1. HAL库介绍2. STM32Cube固件包3. HAL库框架结构4. 新建HAL版本MDK工程 STM32HAL库 1. HAL库介绍 HAL库 HAL&#xff0c;英文全称 Hardware Abstraction Layer&#xff0c;即硬件抽象层。HAL库是ST公司提供的外设驱动代码的驱动库&#xff0c;用户只需要调…

CentOS找回root密码

很悲伤&#xff0c;你忘记了root密码。。。 那就来重置它吧~ 1、在启动时选择操作系统&#xff1a;在引导过程中&#xff0c;选择CentOS操作系统并按下键盘上的任意键来停止引导。 2、 进入编辑模式&#xff1a;在启动菜单中&#xff0c;找到并选择要编辑的CentOS条目&…

科锐16位汇编学习笔记 04 乘除和移位指令

乘法和除法指令用的不多,因为效率很低 比较指令CMP (compare) •格式&#xff1a;CMP OPD&#xff0c;OPS •功能&#xff1a;(OPD) — (OPS),跟减法指令很像,但是不存结果 •说明&#xff1a;目的操作数减去源操作数&#xff0c;然后根据结果设置标志位&#xff0c;但该结…

Hyperledger Fabric 通道配置文件解析

fabric 版本 v2.4.1 Fabric 网络是分布式系统&#xff0c;采用通道配置&#xff08;Channel Configuration&#xff09;来定义共享账本的各项行为。通道配置的管理对于网络功能至关重要。 通道配置一般包括通道全局配置、排序配置和应用配置等多个层级&#xff0c;这些配置都存…

红队打靶练习:RICKDICULOUSLYEASY: 1

目录 信息收集 1、arp 2、nmap 3、nikto 4、whatweb 目录探测 gobuster dirsearch WEB get flag1 /robots.txt FTP get flag2 telenet登录 get flag3 get flag4 9090端口 get flag5 dirsearch ssh登录 Summer用户 get flag6 信息收集 get flag7 get fl…

学习笔记之——3D Gaussian Splatting及其在SLAM与自动驾驶上的应用调研

之前博客介绍了NeRF-SLAM&#xff0c;其中对于3D Gaussian Splatting没有太深入介绍。本博文对3D Gaussian Splatting相关的一些工作做调研。 学习笔记之——NeRF SLAM&#xff08;基于神经辐射场的SLAM&#xff09;-CSDN博客文章浏览阅读967次&#xff0c;点赞22次&#xff0…

CHS_01.1.4+操作系统体系结构 一

CHS_01.1.4操作系统体系结构 一 操作系统的体系结构 也就是操作系统的内核应该怎么设计这样一个问题操作系统的内核 在这个小节中 我们会学习 操作系统的体系结构 也就是操作系统的内核应该怎么设计这样一个问题 那这个小节的内容我们只需要做简要的了解就可以了 我们考试中常考…

GAMES101-Assignment4

一、问题总览 实现de Casteljau算法来绘制由4个控制点表示的Bzier曲线。需要修改main.cpp中的如下函数&#xff1a; bezier&#xff1a;该函数实现绘制Bzier曲线的功能。它使用一个控制点序列和一个OpenCV::Mat对象作为输入&#xff0c;没有返回值。它会使t在0到1的范围内进行…

Java中什么序列化?

在Java中&#xff0c;序列化是一种将对象转换为字节序列的机制&#xff0c;使得对象可以在网络上传输或存储到文件中&#xff0c;而后可以通过反序列化还原为对象。Java提供了java.io.Serializable接口&#xff0c;通过实现这个接口的类可以实现对象的序列化和反序列化。 序列…

翻译:Building Efficient RAG Systems: A Deep Dive into devv.ai

RAG 的全称是&#xff1a;Retrieval Augmented Generation&#xff08;检索增强生成&#xff09; 最初来源于 2020 年 Facebook 的一篇论文&#xff1a;Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks&#xff08;是的&#xff0c;你没有看错&#xff0c;…