C语言常用知识(常更新)

基础知识

  1. C语言的编译和链接

编译型语言:程序在执行之前需要有一个专门的编译过程,编译成机器语言。e.g. C, C++

特点:依赖编译器

C语言代码需要经过编译和链接生成可执行程序才能运行

过程:源文件>>预编译(生成“.i”文件)>>编译(生成二进制的目标程序.obj)>>汇编>>链接>>可执行程序

注意

  1. 编译程序能生成≠程序无错误;逻辑错误需要通过调试发现

解释性语言:HTML,XML,Python,Ruby

  1. 集成开发环境IDE

编写代码
VS上要运行代码需要:

1)编译+链接

2)运行

做法:按键ctrl+F5(笔记本电脑注意fn)

注意区别:F5是调试!

  1. C中的源文件(.c)和头文件(.h)

  2. 在C的源程序中,main函数的位置可以任意

但是:如果代码放main()函数后面的话,要在main()之前声明。先声明再调用

  1. define属于预处理命令,作用是文本替换
  2. C 语言程序的三种基本控制结构是顺序结构、分支(又称选择)结构和循环结构;
  3. 运算符:在算术、赋值和关系运算符中,按照优先级从高到低的顺序排列为:算术运算符、关系运算符、赋值运算符。(算官富
    • 双目运算符(需要两个操作数)和单目运算符(1个操作数)(+,-表正负)
  4. C语言的历史:1983年美国国家标准化协会制定ANSI C
  5. C语言的特点:
    • 是结构化语言
    • 语句借鉴紧凑,使用方便灵活
    • c语言程序易于移植
    • 有强大处理能力
    • 目标代码质量高,运行效率高
  6. 复合语句;语法上视为一条语句

变量类型

1.单精度浮点型float
最多有7位十进制有效数字,四舍五入 e.g. 3.1415926535 --> 3.141593

输出格式控制符

  • 整型输出时,输出8进制:“%o”, …; 输出十六进制: “%x”, …
  • 添加宽度限定词: e.g.整型输出:%md, 指定输出宽度m(包括符号位);实际位数<m, 左端补空格;>m, 根据实际位数输出;
    又e.g. 实型数据输出%m.nf, 保留n
    位小数,输出宽度是m(包括符号和小数点),补空格规则同上. e.g. %6.1f 表示按照右对齐的方式输出实数,总共输出6位,其中小数保留1位,不足六位就用空格补上
    若要左对齐,则用%-6.1f

For循环

for (表达式1; 表达式2; 表达式3) 
    循环体语句 

for语句的表达式2若为空,则表示真值,常常会导致循环无限制条件而死循环。

  • 循环体语句只执行一条;若有多条,需要变为复合语句。
  • 表达式3执行,是在执行完循环体语句之后。表达式2,3重复执行,表达式1只在循环前执行1次
  • 循环(控制)变量:for循环中,通过改变或判断某个变量的值来控制循环的执行。
  • 若for()语句后有个分号,编译器会认定是for()语句后紧跟这一条空语句(作为循环体语句)(见以下代码)
//...
int fahr;
double celsius;   
for (fahr = 121 ; fahr <= 125; fahr++) ;  //执行空语句5次,结束时fahr = 126;
    celsius = 5.0 * (fahr - 32) / 9.0;         /* 语句① */  //执行1次
    printf("%4d%6.1f\n", fahr, celsius);       /* 语句② */  //执行1次

函数

一般来说函数要写在main函数之前,但当自定义函数数量过多,会影响main函数被阅读;
解决方法:在main函数前率先进行自定义函数的声明。
函数声明:可以写在开头,便于之后所有的函数都能调用之。

局部变量和全局变量

局部变量:
1)在函数内定义(including形参)
2)定义在复合语句内部

全局变量:在函数以外定义的变量,不从属于任何一个函数
全局变量有初始值,默认为0;从程序执行开始,到程序结束,存储单元始终保持。
作用范围:从定义处到源文件结束。
**若局部变量与全局变量同名,(共同作用范围内)局部变量优先。

##变量生命周期和静态局部变量
生命周期:从其产生(每次函数调用时,为其分配存储空间),到其消亡(每次该函数调用结束,变量的存储单元被回收)
自动变量:以前所称的局部变量

全局变量比局部变量自由度大,因此应该谨慎使用,因为每一个函数调用都有可能改变其的值。

静态局部变量

static 类型名 变量名
作用范围:局部变量
生命周期:同全局变量;
在静态局部变量作用范围内,静态变量的初值为0,且其会记住前一次调用时留下来的值。

数据类型和储存

原/反/补码

正数的三码相同
负数:反码:符号位不变,原码取反;补码:
使用补码的好处:避免了反码中出现的两个零?:-0和+0,只有一个零
根据补码的原理,16位2进制,能表示的正数最大值只有32767,否则会溢出。再加1,会向下循环到-32768

整数

整数的表示

  1. 十进制
    首位不可为0.
  2. 八进制
    +/-, 0-7, 首位是0.
  3. 十六进制
    +/-, 0-9,a-f/A-F(大小写等价)前缀0x/0X.
    e.g.以下三种形式等价
    十 八 十六
    123 0173 0x7b
    16 020 0x10

整数类型

  1. 字母后缀
    e.g. 123L (long)
    123U (unsigned)
    123LU (unsigned long)
    -8U -->非法数据
  2. 整数的值

整型数据的输入输出

系统输出时,不管以何进制,输出都是没有前导的0(八进制)和0x(十六进制)的。
不同的格式控制说明符只是改变数据输出的形式,实际数据还是同一个。

输入scanf()

%e: 以科学计数法的格式接收数值

字符型数据

  1. 字符具有数值特征 (在ASCII码范围内)
    e.g. ‘A’ 65 0100 0001 等价
    char c = 65; ---->合法语句
    ‘A’ + 1 = 66;
  2. ASCII字符集
    0-9:
    A-Z: 65-90
    a-z: 97-122
    C语言一个独有特点:字符‘1’可以进行运算(以ASCII码值的形式)

转义字符

  • 是字符常量,代表一个字符
  • 所有字符都可以用转义字符表示
  • \t: 横向跳格(tab键作用)
  • \b: 显示输出时,刷新左边一个字符
  • \: 反斜杠字符""
  • ': 单引号
  • \r: 回车(输出位置重新移到行首)
    e.g. printf(“Hello world\rHello Hangzhou”);
    输出“Hello Hangzhou”
  • \ddd: 八进制数ddd代表的字符
    \401–>非法(超出ASCII码范围)
    \007 = \7; \101 = ‘A’
    \后不写0也可以,因为\后无十进制用法
  • \xhh: 十六进制数hh(最多两位)所代表的字符,e.g. \x41 = ‘A’

\401: 系统识别为’ '和‘1’

实型

  1. 数据精度和取值范围是两个不同概念
    e.g. float x = 1234567.89 (在取值范围内,但不能精确表达)
    e.g.2

实型常量

  • 科学技术法
    e.g.

类型转换

  1. 强制类型转换: (类型名)表达式, 优先级最高
    e.g. (double)3; (int)3.8

表达式

x++:
++x:
两者单独使用是等效的;但作为表达式的一部分就有差异了。
e.g. i= -1;

算数运算符的优先级和结合性

数组

  1. ANSI C标准下,定义数组需要明确数组名,元素类型和数组的大小
  2. 数组名表示该数组所分配连续内存空间中第一个单元的地址(首地址)。由于数组空间一经分配后,在运行过程中不会改变。因此,数组名是一个地址常量,不允许修改。
  3. 引用:只能引用单个元素,不允许引用整个数组;引用数组元素时,方括号内表达式可以是变量;
  4. 静态数组:可初始化。e.g.
    static int b[5] = {1,2, 3, 4, 5};
    如果静态储存数组没有初始化,系统自动给所有的数组元素赋0.
    只对部分元素赋值,其余元素初值为0;

变量

变量赋初值:使用的‘=’不是赋值号
e.g. static int a = 1;
{static int a; a=1;}.
两者不一样

一维字符数组 vs 字符串

  1. 存放字符型数据。e.g. char t[6] = {‘H’, ‘a’, ‘p’, ‘p’, ‘y’ };

  2. 部分初始化:其余未赋值元素为0
    等价于:char[6] = {‘H’, ‘a’, ‘p’, ‘p’, ‘y’, 0};

  3. 0代表’\0’, ASCII码为0
    等价于:char[6] = {‘H’, ‘a’, ‘p’, ‘p’, ‘y’, ‘\0’};

  4. 字符串常量:双引号括起来的字符序列,有一个结束标志’\0’;
    e.g. 字符串"Happy"由6个字符组成: ‘H’, ‘a’, ‘p’, ‘p’, ‘y’ 和’\0’;
    前五个为字符串的有效字符,'\0’是字符串结束符

  5. 字符串的有效长度就是有效字符的个数; e.g. "Happy"的有效长度是5;

  6. C语言将字符串作为一个特殊的一维字符数组来处理:

  • 字符串的存储-数组初始化

    • 字符串可以存放在一维字符数组中:
      static char s[6] = {‘H’, ‘a’, ‘p’, ‘p’, ‘y’, ‘\0’}; //数组s中存放了字符串"Happy";
    • 字符数组的初始化也可以使用字符串常量
      等价于:static char s[6] = {“Happy”};
      or static char s[6] = “Happy”;
    • 字符串存入字符数组时,由于存在结束符’\0’, 数组长度 至少是字符串的有效长度+1
    • 数组长度 > 字符串有效长度+1, 则数组中除了存入的字符串,还有其他内容,即字符串只占用了数组的一部分。e.g.
      auto char str[80] = “Happy”;
      只对数组的前6个元素(str[0] - str[5])赋初值,其他元素的值不确定。然而,不会影响对字符串”Happy“的处理。因为字符串遇’0’结束,数组中第一个’\0’前面的所有字符和第一个’\0’一起构成了字符串"Happy"; 第一个’\0’之后的其他数组元素与该字符串无关。
  • 字符串的操作

    • 字符串存入一维字符数组后,对字符串的操作即为对该字符数组的操作。但需要注意:
      • 普通数组:元素个数确定,用下标控制循环;
      • 字符串:没有明显给出有效字符个数,只规定’\0’之前都为有效字符,通过==比较元素值是否等于’\0’==控制循环。
  • 字符串的存储:赋值和输入

  • e.g. static char s[80];
    s[0] = ‘a’;
    s[1] = ‘\0’; (赋值)

等价于: static char s[80] = “a”;(输入)
区别:
“a”: 字符串常量,包括’a’ 和’\0’两个字符,用一维数组存放;
‘a’: 字符常量,只有一个字符,可以赋给字符变量

注意:输入(字符串)时,由于后面的结束符’\0’无法输入,因此,输入时需要事先指定输入结束符,代表输入结束,并将输入结束符转换为字符串结束符’\0’;

再次强调:把字符串存入数组后,对字符串的操作就是对字符数组的操作!

指针

定义

  • 直接访问
  • 间接访问:通过另一个变量访问变量的内容。把变量的地址放到另一变量中,使用时先找到后者,再从中取出前者的地址。e.g. p指向a, *p==a
  • 指针变量:存放地址的变量。若指针变量p存放了变量x的(首)地址,则p指向x;
  • 定义: …
  • 指针必须先赋值再引用,可将其赋值为NULL或数组首地址。

悬挂指针

e.g. int *p; *p=5; 会在随机空间内改变储存变量的内容,有害

数组和指针的关系

任何由数组下标来实现的操作都能用指针来完成
以下两式恒等价:
*(a+i) (指针法表示元素)
a[i] (下标法表示元素)
甚至有时没有定义数组,使用[]也可以,编译器会理解成指针

  • 数组的循环也可以使用指针
  • e.g.
  • for (p=a; p<=&a[i]; p++) (表达式2还可以写成p<=a+99)
  • 当仅引用(或称呼)地址,而没有访问数组边界外的内容时,是不算越界的
  • e.g. a[0] == *(&a[-1]+1) 没有访问a[-1],之势引用了其地址
  • 定义函数时,使用int a[]作为形参,也相当于int *a作为形参

结构

定义和初始化

  • 定义结构体类型定义时不可以初始化;此时赋值是没有空间储存之的。
  • 定义方式:
    1. 混合定义:定义结构类型的同时定义结构变量
    1. 无类型名定义:定义结构时省略结构名,变量必须立刻在结构后定义完
  • 初始化:按照结构定义时分量的描述顺序给出各个分量的值

结构变量的使用

  • 具有相同类型的结构变量可以直接赋值
嵌入式C语言是针对特定硬件平台设计的一种编程语言,它的语法与标准C语言相似,但为了适应资源有限的环境,通会有所简化和优化。以下是一些关键的嵌入式C语言常用语法知识点: 1. 数据类型:见的有基本数据类型(如int、char、float)、结构体(struct)、共用体(union)、枚举(enum)以及定义硬件特有的数据类型(如GPIO引脚状态等)。 2. 变量声明和初始化:在嵌入式中,注意内存分配的效率,可能需要预先定义变量或者使用静态存储区。 3. 功能库使用:许多嵌入式系统有自己的API或库,例如UART通信、GPIO控制、中断管理等,要了解如何正确调用这些函数。 4. 函数定义和调用:嵌入式程序往往依赖于函数的模块化设计,可能涉及到中断服务程序(ISRs)和裸中断。 5. 预处理指令:#define、#include、#ifdef、#ifndef等用于宏定义、头文件引用和条件编译。 6. 指针:嵌入式系统中指针的使用非频繁,特别是在内存管理和硬件操作中。 7. 操作符重载和运算符优先级:由于资源限制,嵌套操作可能较少见,但理解基本的运算符优先级仍然重要。 8. 错误处理和异处理:考虑到资源有限,嵌入式程序通更注重错误检查和简单的异处理机制。 9. 结构化编程:循环、分支结构(if-else、switch)、递归等控制流结构必不可少。 10. 低级别硬件交互:可能会直接操作寄存器或者访问内存地址,理解和编写汇编代码的知识被要求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值