记录每次学习的过程,总结学习的内容,希望能给到自己和别人帮助。
嵌入式学习-C语言-基础语法
语言分类
编译型语言:例如C、C++
解释型语言:例如Python、JS
区别:
编译型语言只要翻译1次
解释型语言每次运行都要逐行翻译
标识符命名/命名规则
命名规则(数字、字母、下划线)见名知意
● 规则说明:
○ 只能由数字、字母、下划线_组成;
○ 不能使用数字开头;
○ 不能使用关键字;
○变量名之间大小写是区分的;
命名分类:
大驼峰 MyFirstName
小驼峰 myFirstName
下划线命名my_first_name
数据类型
可移植类型
C语言在可移植类型 stdint.h 和 inttype.h 中规定了精确宽度整数类型
#include <stdio.h>
#include <inttypes.h>
int main() {
// 8位整型
int8_t a=127;
printf("%d\n", sizeof(a));
// 16位整型
int16_t b = 127;
printf("%d\n", sizeof(b));
// unsigned 无符号,没有符号位,数值为正数
uint8_t c = 255;
uint16_t d = 200;
return 0;
}
数据类型长度
特殊类型:char
char类型
char表示为字符类型,用于存储单个字符,每个字符变量都是由8个bit位构成,在内存中就是1个字节。
相关特性:
● 在给字符型变量赋值时,需要用一对英文半角格式的单引号(’ ')把字符括起来。
● 字符变量在内存单元存储时,是将与该字符对应的ASCII码放到变量的存储单元中。
char的本质就是一个1个字节大小的整型
常量
常量不可修改(常量的值在程序运行时不会改变)
两种方法:
//1.预处理常量,没有分号(在main之前)
//预处理关键字 常量名 常量内容
#define PI 3.14
// 2.const常量(在方法里)
const修饰的变量就是常量,不可修改
//关键字 类型 常量名 常量内容
const double pi2 = 3.14;
进制
二进制
● 二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数
○ 它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”
● 当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的
● 十进制转化二进制的方法:
○ 用十进制数除以2,分别取余数和商数,商数为0的时候,将余数倒着数就是转化后的结果
口诀:除二取余,倒序排列法
八进制:
● 八进制,Octal,缩写OCT或O,一种以8为基数的计数法,采用0,1,2,3,4,5,6,7八个数字,逢八进1
○ 一些编程语言中常常以数字0开始表明该数字是八进制
● 八进制的数和二进制数可以按位对应(八进制一位对应二进制三位),因此常应用在计算机语言中
● 八进制和二进制互转:
● 十进制转化八进制的方法:
○ 用十进制数除以8,分别取余数和商数,商数为0的时候,将余数倒着数就是转化后的结果
十六进制:
● 十六进制(英文名称:Hexadecimal),同我们日常生活中的表示法不一样,它由0-9,A-F组成,字母不区分大小写
○ 与10进制的对应关系是:0-9对应0-9,A-F(或a-f)对应10-15
● 十六进制的数和二进制数可以按位对应(十六进制一位对应二进制四位),因此常应用在计算机语言中
● 十六进制和二进制互转:
● 十进制转化十六进制的方法:
○ 用十进制数除以16,分别取余数和商数,商数为0的时候,将余数倒着数就是转化后的结果
进制的表示:
十进制 | 以正常数字1-9开头,如15 |
---|---|
八进制 | 以数字0开头,如017 |
十六进制 | 以0x或0X开头,如0xf |
二进制 | 以0b或0B开头,如0b1111 |
#include <stdio.h>
int main() {
// 十进制方式赋值
int a = 15;
// 八进制方式赋值
int b = 017;
// 十六进制方式赋值
int c = 0xf;
// 二进制方式赋值
int d = 0b1111;
printf("%d, %d, %d, %d\n", a, b, c, d);
return 0;
}
数值存储方式-原码/反码/补码
反码
为了解决上面的问题,出现了反码,反码的计算规则如下:
● 正数的反码就是原码本身;
● 负数的反码是按位取反(但符号位不变);
● 1 -> 0000 0001 -> 0000 0001
● -1 -> 1000 0001 -> 1111 1110
补码
正数的补码就是原码本身;
负数的补码就是在反码的基础上+1;
● 1 -> 0000 0001 -> 0000 0001 -> 0000 0001
● -1 -> 1000 0001 -> 1111 1110 -> 1111 1111
进制转换
二进制直接转八进制
—八进制一位对应二进制的三位 一对三
例如:八进制的76321转换成二进制:
八进制: 7 6 3 2 1
二进制:111 110 011 010 001
二进制 与 十六进制的转换
—十六进制的数和二进制数可以按位对应(十六进制一位对应二进制四位),因此常应用在计算机语言中 一对四
● 十六进制(英文名称:Hexadecimal),同我们日常生活中的表示法不一样,它由0-9,A-F组成,字母不区分大小写
○ 与10进制的对应关系是:0-9对应0-9,A-F(或a-f)对应10-15
例如:十六进制的a6b2f1转换成二进制:
十六进制:a 6 b 2 f 1
二进制: 1010 0110 1011 0010 1111 0001
运算符
算术运算符
#include <stdio.h>
int main() {
// 2数相除,要想得到小数的结果,分子分母必须有一个数是小数
double c = 5/2; // 5, 2个都是整数,只会取整
printf("c1 = %lf\n", c);
c = 5.0/2;
printf("c2 = %lf\n", c);
c = 5/2.0;
printf("c3 = %lf\n", c);
int i = 0;
// 前置++
// 先加后用
int b = ++i;
printf("前置:b = %d, i = %d\n", b, i);
// 后置++
// 先用后加
i = 0;
b = i++;
printf("后置:b = %d, i = %d\n", b, i);
return 0;
}
结果是:
c1 = 2.000000
c2 = 2.500000
c3 = 2.500000
前置:b = 1, i = 1
后置:b = 0, i = 1
赋值运算符
#include <stdio.h>
int main() {
int a = 10;
a += 5;
printf("a = %d\n", a);
return 0;
}
结果是:
a = 15
比较运算符
C 语言的比较运算中, “真”用数字“1”来表示, “假”用数字“0”来表示。
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
printf("%d\n", a == b);
printf("%d\n", a != b);
printf("%d\n", a > b);
printf("%d\n", a < b);
printf("%d\n", a >= b);
printf("%d\n", a <= b);
return 0;
}
逻辑运算符
#include <stdio.h>
int main() {
// &&(与),可以理解为并且
// 案例:请判断班长和他女朋友是否符合法定结婚年龄
int boy = 25;
int girl = 21;
int result = boy >= 22 && girl >= 20;
printf("%d\n", result);
// ||(或),可以理解为或者
// 案例:班长女朋友玩原神没有原石了,请帮班长判断是否有足够的钱
double wx_money = 100;
double alipay_money = 300;
result = wx_money >= 398 || alipay_money >= 398 || wx_money+alipay_money >= 398;
printf("%d\n", result);
// !(非),可以理解为不是
printf("%d\n", !0);
printf("%d\n", !!1);
// 短路规则
// && 左边为假,右边不执行
0 && printf("我是右边\n");
// || 左边为真,右边不执行
1 || printf("我是右边\n");
return 0;
}
位运算符(重点难点)
常见的位运算符号有&、|、^、~、>>、<<,分别代表着如下含义:
小结汇总公式:
公式推导过程
假设是第n位需要操作
置0:数 & (1<<n)
置1: 数 | (1<<n)
取反: 数 ^ (1 << n)
取值:(数 & (1<<n))>> n
// 将变量a的第2位设置为1,其他位保持不变
uint8_t a = 0b10110011; // 0xb3;
// 0b1011 0111 b7
printf("第2位设置为1: %#x\n", a | (1 << 2));
// 0b10110011 原来的数
// 0bxxxxx1xx 第2位和1按位或,第2位即可变成1,问题是,其它位不变,0和原来的位按位或,维持不变
// 0b10110011 原来的数
// 0b00000100 按位或的数 0x04 1 << 2 就是0x04
printf("第2位设置为1: %#x\n", a | 0x04);
// 将变量b的第2位、第6位设置为1,其他位保持不变
uint8_t b = 0b10110011; // 0xb3;
// 0b11110111 // f7
uint8_t temp = b | (1 << 2);
temp = temp | (1 << 6);
printf("第2位、第6位设置为1: %#x\n", temp);
printf("第2位、第6位设置为1: %#x\n", b | ((1 << 2) | (1 << 6)));
// 将变量c的第5位设置为0,其他位保持不变
uint8_t c = 0b10110011; // 0xb3;
// 10010011 0x93
printf("第5位设置为0: %#x\n", c & ~(1 << 5));
// 0b10110011 原来的
// 0bxxyxxxxx y和第5位,位运算一定变为0, 一个位和0按位与,一定变成0,问题是,其它位不变
// 上面已经确定是按位与&,一个位和1按位&,维持不变
// 0b10110011 原来的
// 0b11011111 df 按位& , ~(1 << 5) 就是0xdf
// 0b10010011
printf("第5位设置为0: %#x\n", c & 0xdf);
// 将变量d的第0~3位设置为0,其他位保持不变
uint8_t d = 0b11111111; // 0xff;
printf("第0~3位设置为0: %#x\n", d & ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3));
printf("第0~3位设置为0: %#x\n", d & 0xf0);
// 将变量e的第2位取反,其他位保持不变
uint8_t e = 0b10110011; // 0xb3;
// 0b10110111 // 0xb7
printf("第2位取反:%#x\n", e ^ (1 << 2));
// 0b10110011 原来的数
// 0bxxxxxyxx 一个位和y按位异取反,y为1,x为0
// 0b10110011 原来的数
// 0b00000100 异或的数 0x04 (1 << 2) 就是0x04
printf("第2位取反:%#x\n", e ^ 0x04);
// 将变量dat取出8-15位
uint32_t dat = 0x12345678;
// 0xyyyyzzyy 0x0000ff00 按位与 &,还得右移8位
printf("%#x\n", (dat & 0x0000ff00) >> 8);
凡心所向,素履以往,生如逆旅,一苇以航。