学嵌入式C语言,看这一篇就够了(3)
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250219234859546-357927227.pngC语言的基本元素
我们通过写一篇文章的方式来类比写一段程序,从而熟悉一下C语言有哪些基本元素:
一篇文章 --> 若干段落 --> 几条语句 --> 几组词(单词 + 语句)--> 若干个字
一段程序 --> 若干函数 --> 几组语句 --> 表达式 --> 标识符 --> 字符
自然语言字词句段章单词短语C语言字符标识符表达式语句函数写一个程序相当写一篇文章,而一篇文章(程序)是由多个段落(函数)构成的,一个段落(函数)是由多个句子(语句)构成的,一个句子(语句)是由多个短语(表达式)构成的,一个短语(表达式)是由多个单词(标识符)构成的,一个单词(标识符)是由多个文字(字符)组成的
[*]常用汉字有3500左右,常用英语单词有6000左右,那么想要掌握C语言必要学习多少个关键字(keywords)?
[*]C语言关键字有32个,都是小写的,英文单词的缩写。
[*]int -- integer 整数;char -- character 字符; if 如果;continue 继承......
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220004548614-817471603.png
计算机储存器结构
数据的概念
利用计算机的目的就是为了高效的处理大量数据,但是数据的类型有很多,比如声音、图像、文字、数字等,计算机不用区分数据,计算机只采用二进制存储。
[*]计算机把还未处理的数据以及处理好的数据保存到哪里呢??
[*]这些数据都是存储在存储器,用户通过输入设备(键盘)录入的数据都是先存储在内存中,然后控制器会把这些数据通报给运算器,运算器处理完成后通报给控制器,控制器吧数据通报给输出设备(显示器)
内存的概念
对于计算机中的存储器而言,一般分为两种:RAM(随机存储器)和 ROM(只读存储器)
博客:ROM和RAM的区别
[*]只读存储器
只读存储器的英文全称是Read Only Memory,简称为ROM,属于非易失性存储设备,指的是掉电不丢失数据,可以把数据长时间存储,一般分为很多种,具体的区别可以通过《数电》进行了解,对于计算机的机器硬盘大概固态硬盘而言指的就是ROM
[*]随机存储器
随机存储器的英文全称是Random Access Memory,简称为RAM,属于易失性存储设备,指的是掉电会丢失数据,但是读写速率很快。所以一般CPU都是直接和RAM打交道
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220134236055-1365541043.png
对于计算机的内存条而言,其实指的就是RAM,RAM的内存空间越大,CPU处理数据越多
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220134340168-1607498039.png
[*]数据输入到计算机之后,计算机的CPU是如何知道数据存放在内存的位置?
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220134523090-1047143185.png
内存的单元
内存中一个MOS管可以存储一个二进制数0或1,为了方便影象,标准规定把一个二进制数用bit来进行表现,bit(比特)是binary digit的缩写,中文翻译为位。专业术语一般把一个二进制数称为一位二进制数。所以bit就用来表现计算机数据的最小单元
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220135322246-90362155.png
博客:内存是怎么制作的?
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220135057991-1692301805.png
[*]注意:计算机处理数据的基本单元是byte,计算机处理数据的最小单元是bit,1byte = 8bit
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220135533721-1260093659.png
C语言的常量变量
内存是一块连续的空间,而且内存中的每个存储单元(8bit)都有对应的编号,而且编号是固定的,对于存储单元的编号,一般称为存储单元的地址,用户可以直接通过存储单元的地址来对存储单元进行读写访问,但是一般情况下用户是不会直接通过地址来访问,由于访问效率太低。
常量和变量
C语言标准规定:用户有权利从内存中申请一块存储单元,而且用户可以对存储单元进行命名,要求用户提前阐明申请的存储单元(单元以字节来计算)的巨细,这样内核才会从内存中探求一块合适的空间,并把这块空间的地址反馈给用户
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220135626725-1655740999.png
用户可以对内核提供的存储单元进行命名,然后内核会把用户的命名和存储单元的地址创建一个映射关系,这样用户就可以通过存储单元的名称来访问存储单元
[*]既然用户可以对申请的存储单元进行命名,那请问用户是可以随意命名还是遵照规则?
[*]C语言标准中规定根据数据在程序运行期间的值是否发生变化,可以存储单元分为两种:常量 or 变量
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220140335844-1181298431.png
[*]常量
常量指的是在程序运行期间值不会发生改变的量,一般利用的数字,比如3.14用来表现圆周率,一般情况下,用户都是用通过宏界说的方式来实现常量的计划,宏界说其实就是简单的文本更换,在预处理阶段预处理器会把程序中的宏界说进行展开。C语言中规定宏界说利用预处理指令 #define 来进行计划
[*]变量
变量指的是在程序运行期间值可能发生变化的量,用户可以根据实际必要来向kernel(内核)申请一块存储单元,并对这块存储单元进行命名,然后用户可以随时修改存储单元中的数据。申请的存储单元的巨细可以通过C语言中的数据类型进行指定
命名规则
变量和常量也被称为标识符,对于标识符的命名必须遵照规则:标识符是由字母、数字、下划线以及美元符号$组成,而且标识符的第一个字符只能是字母大概下划线。
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220140910741-1011653604.png
123m(错误)m123 _m123 _123 _12m M12a_ m12a_ INT Main
[*]注意:为了防止二义性出现,C语言标准规定不可以把体系保留字,以及程序中已经存在的函数名称、以及用户已经界说出来的标识符名称作为新的标识符名称(同一个作用域内不能)。
[*]C语言的标识符是区分巨细写,而且作为用户而言,标识符的命名应该是有意义的!!!
驼峰命名法:secondsperyear;second_per_year;_myData
C语言的数据类型
[*]既然用户申请存储单元的时候要阐明存储单元的巨细,请问如何让计算机知道巨细?
[*]C语言中提供了一些关键字,专门用于表现数据的类型,其实就是用于表现要申请的内存空间的巨细
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220141045469-1048602096.png
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220141136701-1014515509.png
[*]已知计算机只熟悉二进制,也就是数据都是以二进制形式存储到内存中,请问为什么还必要这些关键字来表现数据的类型?
[*]程序是给人看的,这些关键字是用于提高程序可读性的,另外这些关键字也是阐明数据的宽度的(占几个字节)
[*]字符型
C语言标准中提供了一个关键字char,其实是character单词的缩写,表现字符的意思,操作体系char类型的数据宽度界说为1字节,用于存储字符,C语言标准中用单撇号' '表现字符
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220144148095-1336068655.png
[*]C语言标准规定:用户打算存储必要按照规则字符 数据宽度变量名称 ;举例: charch=‘c’
C语言标准中关于字符的种类有两种:普通字符 and 转义字符,对于ASCII码表中转义字符
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220144459605-2067479046.png
注意:ASCII码中的转义字符必要利用 ‘\0’‘\r’‘\n’进行表现,代表字符具有特别的意义。
已知计算机是以二进制存储数据,意味着写入到存储器中的字符都会被编译器转换为而二进制指令,那请问用户能否直接以二进制指令的形式把字符输入到存储器中,编译时是否会报错??
回答:会报错,因为C语言不支持二进制输入,但是C语言支持八进制、十进制、十六进制。
[*]整数型
C语言标准中利用关键字int表现整数,关键字int的英文单词是integer,对应的中文具有整数的寄义,在32体系下关键字int的数据宽度是4字节,也就意味着存储单元所能存储的整数范围比力广泛
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220144818784-1902148758.png
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220144844864-1606852070.png
C语言标准规定了用户可以采用不同的进制来表现数据,常用的进制有八进制、十进制以及十六进制,而且为了区分这三种进制,所以规定每种进制都有对应的前导符(前缀),规定八进制的前缀以0表现,比如064,规定十六进制的前缀以0x/0X表现,比如0x64。
具体的转换规则可以看《数字电路》
[*]短整型
C语言标准中规定利用关键字short来表现短整型,一般短整型的全称是short int,只不外写程序的时候可以只写short即可,在32位体系下short短整型占2字节
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220145305941-426468609.png
[*]长整型
C语言标准中规定利用关键字long来表现长整型,一般长整型的全称是long int,只不外写程序的时候可以只写long即可,在32位体系下long长整型占4字节,在64位体系占8字节
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220145334899-1163959784.png
[*]长长整型
C语言标准中规定利用关键字long来表现长整型,但是长长整型是利用long long来表现,在32位和64位体系下长长整型占8字节
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220145357548-1810340317.png
[*]C语言中提供了char、int、short、long、long long来表现整型,但是整型数是分正负的,编译器如何来区分整数的正负呢?
[*]C语言标准中提供了两个关键字 signed&&unsigned用于修饰整数,unsigned表现无符号,signed表现有符号,C语言中的signed修饰符是隐式声明,也就是用户界说整型变量的时候如果没有特别夸大,则整型变量默认是有符号的
[*]用户如果要存储无符号的整数,则必须界说变量必须显式声明变量是无符号的(unsigned)
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220145742232-544467560.png
[*]计算机可以区分整数的正负,但是程序最终都会被转换为二进制指令,但是二进制是不分正负的,请问编译器是如何转换数据的???
[*]二进制可以分正负,在二进制数的前面添加1bit,作为符号位,而且bit=0,用于表现二进制数为正数,bit=1,用于表现二进制数为负数
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220145904145-1055547393.png
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220145908730-2111379696.png
[*]计算机内部是以二进制的补码方式来存储数据的,所以必要把二进制数的原码转换为补码形式
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220145932525-649749697.png
[*]正数的原码和补码是相同的,所以负数才必要把原码转换为补码,再进行存储!
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220150205890-556328865.png
反码:二进制数除了符号位(二进制数中的最高位),把数据位取反即可(0变1,1变0)
-1--- 1 000 0001 原码 -- 计算反码 -- 1 111 1110 反码
补码:二进制数的反码 + 1
-1 -- 1 000 0001 原码 --计算反码 -- 1 111 1110 反码--计算补码 -- 1111 1110 +1 -- 1111 1111
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220150327136-1073607639.png
[*]练习:用户打算界说一个字符型变量,命名叫做data,准备把一个正整数存储到变量data中,并计划了一段程序,请问这段程序输出的效果是多少?
[*]char data; data = 128; printf(“%d\n”,data);--> 请问输出的效果是多少??答案:-127
128--0000 0000 0000 0000 0000 0000 1000 0000原码--正数的原码和补码是相同的 1000 0000
1000 0000补码 -- 属于数据类型中非常特别的存在,可以计算是 -0,但是0不分正负,所以 把-0的位置用-128进行更换。
[*]注意:计划程序时,界说的变量如果是有符号的,则尽量制止写入超过变量范围的数值!!!!!!
字符型: char1字节 -- 有符号 -- 数值范围 -128 ~ 127--无符号 -- 数值范围 0 ~ 255
短整型:short2字节 -- 有符号 -- 数值范围 -32768 ~ 32767 无符号 --数值范围 0 ~ 65535
[*]浮点型
数据有整数和小数之分,一般情况下处理的数据也是具有小数的,所以C语言标准中规定利用关键字float来表现单精度浮点数,单精度浮点型占4字节,另外C语言标准中也提供了另一个关键字double用来表现双精度浮点数,double占8字节,其实C语言也提供了一种类型long double,该类型占16字节
C语言中一般表现浮点数有两种方案:十进制形式 or 指数形式,两者的具体区分如下所示
[*]十进制形式
十进制形式是采用整数+小数的组合表现浮点数,比如3.14 、5.0 ,基本上也是最常用的方案
[*]指数形式
指数形式指的是采用以10为底的形式表现浮点数,比如 3.14 * 102 ,但是在编写程序的时候采用英文半角输入法进行计划,这种输入法是不支持输入上标大概下标,所以C语言规定采用字符e大概E来表现以10为底的指数,比如3.14E2
[*]注意:C语言标准中规定字符e/E的后面必须是整数,另外字符e/E的前面必须有数字!!!!!!
[*]思考:用户界说了一个单精度浮点型变量,并把变量命名为a,此时用户不小心把一个整数5存储到了该变量中,请问变量中存储的数是什么? float a;回答:%f5.000000
[*]整型数据在计算机中存储的时候是以二进制补码形式进行存储,请问一个浮点型数据在计算机中是如何存储的?
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220151003733-869388799.png
[*]字符串
字符串是表现某种寄义的一个字符序列,字符串在内存是必要一块连续的内存空间进行存储,C语言中规定字符串利用双引号””表现,而且规定字符串的结束标志是’\0’,但’\0’不必要用户手动添加,体系会自动在一个字符串的末尾添加’\0’
[*]思考:既然在内存中字符串必要一块连续的空间来存储,内核肯定会返回字符串的开始地址,请问内核如何判定字符串何时结束?
[*]回答:遇到’\0’自动结束
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220151133385-495388981.png
[*]布尔型
用户有时候必要在程序进行判定,在C89标准中,用户如果想要判定某种条件是否建立,一般是界说一个整型变量,然后利用数字0和数字1来表现条件是否建立,用户就可以把变量作为一个标志位利用。
在C99标准可以利用布尔型来表现真假两种情况,头文件stdbool.h有相关形貌,在头文件中界说了三个宏,分别是bool、true以及false
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220151226452-1275918979.png
https://img2024.cnblogs.com/blog/3602479/202502/3602479-20250220151228600-802618004.png
思考:已经知道基本数据类型的宽度是取决于体系环境以及编译器,假设用户此时并不清楚当前利用的机器的位数(32bit/64bit)和编译器类型,那应该如何知道基本数据类型的宽度?
回答:
在 C 语言里,若想更简单快捷地知晓基本数据类型的宽度,其实主要还是依赖 sizeof 运算符
编写宏界说简化代码
利用宏界说能够制止重复编写 printf 语句,让代码更简洁,示例如下:
#include <stdio.h>
// 定义一个宏,用于输出指定类型的大小
#define PRINT_TYPE_SIZE(type) printf("Size of " #type ": %zu bytes\n", sizeof(type))
int main() {
// 调用宏输出各种基本类型的大小
PRINT_TYPE_SIZE(char);
PRINT_TYPE_SIZE(short);
PRINT_TYPE_SIZE(int);
PRINT_TYPE_SIZE(long);
PRINT_TYPE_SIZE(long long);
PRINT_TYPE_SIZE(float);
PRINT_TYPE_SIZE(double);
PRINT_TYPE_SIZE(long double);
return 0;
} 代码解释:
- PRINT_TYPE_SIZE 宏借助 # 运算符把类型名转换为字符串,再使用 sizeof 运算符获取该类型的大小,最后用 printf 输出结果。
- 在 main 函数里,只需调用这个宏并传入不同的基本数据类型,就能快速输出各类型的宽度。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]