20240725嵌入式学习笔记

一.起步阶段需要注意养成基本的编程思路

遵循计算机的模型:输入、处理、输出

输入----->CPU----->输出
    数据 处理 数据

准备数据:准备变量
处理数据:通过代码对数据进行操作
输出数据:输出

在操作阶段要遵循“高内聚,低耦合”的编程逻辑。具体含义为: 

在模块化编程时,关联性强的内容集中处理,关联性弱的内容分别处理。

具体在编程过程中的体现为,处理数据时只对数据进行处理;输出数据时只进行输出。避免在输出时对数据进行处理。

为了遵循“高内聚,低耦合”的原则,编程前可以通过绘制流程图的方式来整理思路,明确每一步操作的内容,避免不同层次之间的操作出现交叉。

二.20240724补充

转义字符

ascii码的0~32编码位存放的是不可见字符,即控制字符。其中包含一些特殊字符(转义字符)需要留意: 

常规字符用单引号进行表示,如小写字母n的字符形式为' n '。在n前添加一个反斜杠' \ ',组成新的字符' \n ',这种用反斜杠和字符组成的新字符我们称之为转义字符,在代码中有特殊的用途。

' \n '

换行符,将当前光标位置移到下一行开头处

printf("1234\nABCD");
    
//输出结果:
1234
ABCD

' \t '

水平制表,跳转到下一个tab位置

类似于excel表格,每个tab可以抽象为一个表格,每个表格由八位构成。按一个tab等同于光标右移8位。

printf("12345678ABCD\n");
printf("X\tXX");

//输出结果:
12345678ABCD
X       XX

' \b '

退格,将当前光标位置移到前一位(区别于插入操作)

printf("1234\bABC\n"):

//输出结果:
123ABC

' \r '

回车,将光标移动至本行开头处 

printf("abc*\t123456\rA\tBCD");

//输出结果:
Abc*    BCD456

' \\ '

反斜杠

printf("abc\\ABC\\123\n");

//输出结果:
abc\ABC\123

 ' \' '、' \" '

单引号、双引号

printf("123\'aaa\'123\n123\"bbb\"123\n");

//输出结果:
123'aaa'123
123"bbb"123

转义字符特殊表示方式

转义字符除用十进制ascii值表示外,还可以通过两位十六进制和三位八进制表示

例如大写字母A:十进制ascii编码值表示为' 65 ' ;如果用十六进制表示则为' x41 ';用八进制表示为' 101 '。不过这种方法不直观,较复杂,使用偏少。

三.算数运算

运算符:

加减乘除(+ - * /)

与常规数学计算无差别,均为双目运算符,加减优先级低于乘除。

需要注意两个整数做除法,小数部分被舍去。

取余(%)

13 % 5 = 3

只能对整数对整数取余,小数参与取余运算会报错。取余运算的结果只与左值(%左边的值)有关。取余结果的符号也只与(左值)有关。

计算技巧:对一个正整数X取余,得到的结果的取值范围为0 ~ X - 1。用这个方法,可以将随机数等较大值,在一定范围内取值。

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main(void)
{
    int i = 0;
    srand(time(NULL));

    for(i=0;i < 5;++i)
    {
        printf("%d\n",rand() % 50 + 49);                                                                                         
    }
    return 0;
}   

//运行结果 
64
88
79
68
89

运算符的属性

优先级:运算符有固定优先级,高优先级运算符优先运算。

结合性:同一优先级的运算符在混合运算时按照结合性进行结合。

1 + 2 * 3 - 4  =>=>=  1 + (2 * 3) - 4  =>=>=  (1 + (2 * 3)) - 4

类型转换

强制类型转换

在编程时手动完成。

//强转
int a = 10;
float f = 12.345;
printf("%f\n%d\n",(float)a,(int)f);
//运行结果:
10.000000
12

 隐式类型转换

由程序自动进行的过程,遵循低精度与高精度混合运算时,自动转为对应高精度;float自动转为double,short、char自动转为int。

int a = 10;
float f = 12.345;
printf("%f\n",a * f);
printf("%f\n",a * 2.0);
//输出结果
123.45
20.000000

 自增(++)的两种形式:i++、++i

区别在于i++先取值参与运算,再加一;++i 先加一,再取值参与运算。

共同点为只有在参与运算时才能体现出加一先后的区别,在不参与运算时两者效果均为加一。

从内存空间角度分析二者区别:

i++:自加之前,在内存空间中开辟一片新空间,用于存放自加后的值,但此时如果调用i的值,得到的仍为原值;只有当完整运算过程结束后,新空间中的值才会赋给原空间中的值,赋值结束后,新空间中的内容被释放。

++i:在自加时,直接改变内存空间中 i 的值,无论何时调用 i 的值,都将得到自加后的 i 值。

因此,从内存空间分析可以得知,++i的方式避免了新内存空间的使用,效率更高。

//++i
int i = 0;
a = ++i;
printf("a = %d i = %d\n",a,i);
//运行结果
a = 1 i = 1
//i++
int i = 0;
a = i++;
printf("a = %d i = %d\n",a,i);
//运行结果
a = 0 i = 1

此处涉及到另一个知识点:左值、右值

左值:可被定位的值,即有具体地址的值。

右值:不可被定位的值,即无法取地址的值。

在i++的过程中使用到了一片临时内存空间,在运算结束时内存被释放,因此也被称为匿名变量。匿名变量的地址不明确,无法进行取地址操作。所以 i++也可以成为右值,无法被赋值。

在混合运算中,编译器会将相邻的各种运算符进行分隔,此处用到的知识是贪心法则。贪心法则是编译器处理符号的一种方式:编译器处理的每个符号应尽可能多的包含字符;编译器以从左向右的顺序一个一个尽可能多的读入符号;当读入的字符不可能和已经读入的字符组成合法字符为止。

eg:

a + + + + + b  =>=>=>  a ++ ++ + b  =>=>=>  (a++) ++ + b  =>=>=>  ((a++)++) + b

注意!i++先调值使用,后自加,但与额外代码共同执行时,何时自加是不明确的,无法确定 i 的值何时变化。因此建议最好将 i++运算过程单独进行.

//问题写法
printf("%d %d\n",i,i++);
//建议写法
a = i;
b = i++;
printf("%d %d\n",a,b);

赋值运算(+=、*=、=)

赋值运算的结果就是被赋值的变量的值;赋值运算的类型就是被赋值变量的类型。

    a = b = c = d = 10;
==>                d = 10;
==>           c = 10;
==>      b = 10;
==> a = 10;
//每一次赋值数值为上一赋值过程变量的值;类型为上一赋值过程变量的类型

逗号运算(a = 1,10 + 2,b = 12 + 6)

逗号运算又称顺序求值,按照从左到右的顺序,挨个运算,执行每一个运算式。

逗号运算的结果为最后一个运算式的结果。

不同类型变量混合赋值

高精度向低精度赋值,会出现精度丢失

int a = 12.345;
printf("a = %d\n",a);
//运算结果
a = 12

低精度向高精度赋值

float a = 123;
printf("a = %f\n",a);
//运算结果
a = 123.000000

 长数值向短数值赋值,会出现高位截断

short a = 0x12345678;
printf("a = %#x\n",a);
//运算结果
a = 0x345678

短数值向长数值赋值

有符号短数值向长数值赋值:高位补0;

无符号短数值向长数值赋值:高位补符号位(符号位扩展)。

int a = 0x1234;
int b = 0x8234;
printf("a = %#x b = %#x\n",a,b);
//运算结果
a = 0x1234 b = 0xffff8234

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值