第一周总结

Linux 基础
1. 终端
Ctrl+Alt+t :打开一个终端
命令行输入 exit 关闭终端
Ctrl+d :关闭终端
2. 命令提示符
linux@ubuntu:~ $
^ ^ ^^
1 2 34
1 . 用户名
2 . 主机名
3 . 当前所处的工作路径
~ :用户主目录
4 . $ 普通用户的权限
3. 命令
命令三要素:命令本身、可选项、参数
三者之间要有空格隔开
4.ls
功能:查看当前路径下的内容
ls -a :查看当前路径下所有内容,包括隐藏文件(以 . 开头的文件)
. :当前目录
.. :上一级目录
一切皆文件
ls -l :查看当前路径下的详细信息
drwxr-xr-x 2 linux linux 4096 Aug 10 2020 Desktop
^ ^ ^ ^ ^ ^ ^ ^
1 2 3 4 5 6 7 8
1 . 文件类型
d :目录文件
- :普通文件
s :套接字文件
l :链接文件
c :字符设备文件
b :块设备文件
p :管道文件
2 . 文件权限
rwxr-xr-x
r :可读 w :可写 x :可执行 - :没有对应的权限
文件属主(文件拥有者)、文件属组(同组用户)、其他用户
3 . 文件链接数
4 . 用户名
5 . 同组用户名
6 . 文件大小
7 . 文件最后一次修改时间
5.man 手册
man man :查看 man 手册
man 1 命令:查看命令的用法
man 2 系统函数
man 3 库函数
q 退出
6.cd
功能:切换工作路径
cd 路径:切换到指定的路径
linux@ubuntu:~ $ cd ./Desktop # 切换到当前目录下的 Desktop 目录
linux@ubuntu:~/Desktop $
linux@ubuntu:~ $ pwd
/home/linux
~ = /home/linux
^ ^
1 2
1 . 根目录
2 . 间隔符
相对路径:相对于当前所处的路径
绝对路径:以根目录为起始的路径
cd . :切换到当前目录
cd .. :切换到上一级目录
cd ../.. :切换到上两级目录
cd :切换到用户主目录
cd / :切换到根目录
cd ~ :切换到用户主目录
cd - :切换到上一次使用的路径
TAB 键用法:按一下自动补齐,按两下显示类似名字
7.mkdir
作用:创建目录
mkdir 自定义目录名:创建自定义目录
mkdir -p 父目录 / 子目录:创建多级目录
linux@ubuntu:~ $ mkdir proud
linux@ubuntu:~ $ ls
app Desktop Downloads Music proud Templates work
demo Documents jeffy-vim-read Pictures Public Videos
linux@ubuntu:~ $ cd ./proud
linux@ubuntu:~/proud $ mkdir -p a/b/c
linux@ubuntu:~/proud $ ls
a
linux@ubuntu:~/proud $ ls ./a
b
linux@ubuntu:~/proud $ ls ./a/b 8.touch
8 . 文件名
功能:创建文件
touch 自定义文件名:创建自定义文件
如果文件存在,再 touch 它,就是更改文件最后一次修改时间
方向键上下键:上下查看之前使用过的指令,回车可以确认执行
history :查看之前使用过的指令( 1000 条)
9.cp
功能:复制粘贴
1 . 文件
cp 源文件 目标文件:复制源文件到当前路径
linux@ubuntu:~/proud $ ls
a hello.c
linux@ubuntu:~/proud $ cp hello.c test.c
linux@ubuntu:~/proud $ ls
a hello.c test.c
cp 源文件 路径:复制源文件到指定路径
linux@ubuntu:~/proud $ cp hello.c ./a
linux@ubuntu:~/proud $ ls ./a
b hello.c
linux@ubuntu:~/proud $ cp hello.c ./a/test.c
linux@ubuntu:~/proud $ ls ./a
b hello.c test.c
2 . 目录
cp -r 源目录 目标目录:复制源目录到当前路径
linux@ubuntu:~/proud $ cp a test
cp : -r not specified; omitting directory 'a'
# 不加可选项 -r 会报错
linux@ubuntu:~/proud $ cp -r a test
linux@ubuntu:~/proud $ ls
a hello.c test test.c
linux@ubuntu:~/proud $ ls ./test
b hello.c test.c
cp -r 源目录 路径:复制源目录到指定路径
linux@ubuntu:~/proud $ cp -r test ./a
linux@ubuntu:~/proud $ ls ./a
b hello.c test test.c
10.mv
功能:剪切或重命名
1 . 剪切
mv 源文件 路径:剪切源文件到指定路径
mv 源目录 路径:剪切源目录到指定路径
linux@ubuntu:~/proud $ ls
a hello.c test test.c
linux@ubuntu:~/proud $ mv a ./test # 剪切目录 a 到当前路径下的 test 目录
linux@ubuntu:~/proud $ ls
hello.c test test.c
linux@ubuntu:~/proud $ ls ./test
a b hello.c test.c
linux@ubuntu:~/proud $ mv hello.c .. # 剪切 hello.c 文件到上一级目录
linux@ubuntu:~/proud $ ls
test test.c
linux@ubuntu:~/proud $ ls ..
app Desktop Downloads jeffy-vim-read Pictures Public Videos
demo Documents hello.c
2 . 重命名
mv 源文件 目标文件:重命名文件
mv 源目录 目标目录:重命名目录
linux@ubuntu:~/proud $ ls
test test.c
linux@ubuntu:~/proud $ mv test.c test01.c # test.c 文件重命名为 test01.c
linux@ubuntu:~/proud $ ls
test test01.c
linux@ubuntu:~/proud $ mv test test01 # test 目录重命名为 test01
linux@ubuntu:~/proud $ ls
test01 test01.c
11.rm
功能:删除
1 . 文件
rm 文件名:删除文件
linux@ubuntu:~/proud $ ls
test01 test02.c
linux@ubuntu:~/proud $ rm test02.c
linux@ubuntu:~/proud $ ls
test01
2 . 目录
rm -r 目录名:删除目录
linux@ubuntu:~/proud $ rm -r test01
linux@ubuntu:~/proud $ ls
-i :提示你是否继续这个操作, y 是确认, n 是不执行
linux@ubuntu:~/proud $ rm -i hello
rm : remove regular empty file 'hello' ? n
linux@ubuntu:~/proud $ ls
hello
linux@ubuntu:~/proud $ rm -i hello
rm : remove regular empty file 'hello' ? y
linux@ubuntu:~/proud $ ls
linux@ubuntu:~/proud $
-rf :强制删除
12. 练习
1. 在用户主目录创建以你的名字命名的目录
2. 在该目录下创建 test 目录和 test.c 文件
3. 复制 test 目录和 test.c 文件到当前目录
4. 复制 test.c 文件到 test 目录
5. 剪切 test 目录到用户主目录
6. 删除以你的名字命名的目录
7. 重命名 test 目录为 test01
linux@ubuntu:~ $ mkdir zhouxiang
linux@ubuntu:~ $ ls
app Documents jeffy-vim-read proud Videos
demo Downloads Music Public work
Desktop hello.c Pictures Templates zhouxiang
linux@ubuntu:~ $ mkdir ./zhouxiang/test
linux@ubuntu:~ $ cd zhouxiang/
linux@ubuntu:~/zhouxiang $ ls
test
linux@ubuntu:~/zhouxiang $ touch test.c
linux@ubuntu:~/zhouxiang $ ls
test test.c
linux@ubuntu:~/zhouxiang $ cp -r test ./test02
linux@ubuntu:~/zhouxiang $ ls
test test02 test.c
linux@ubuntu:~/zhouxiang $ cp test.c test02.c
linux@ubuntu:~/zhouxiang $ ls
test test02 test02.c test.c
linux@ubuntu:~/zhouxiang $ cp test.c ./test
linux@ubuntu:~/zhouxiang $ ls ./test
test.c
linux@ubuntu:~/zhouxiang $ mv test ~
linux@ubuntu:~/zhouxiang $ ls
test02 test02.c test.c
linux@ubuntu:~/zhouxiang $ rm -r test*
linux@ubuntu:~/zhouxiang $ ls
linux@ubuntu:~/zhouxiang $ touch test01.c test02.c test03.c
linux@ubuntu:~/zhouxiang $ ls
test01.c test02.c test03.c
linux@ubuntu:~/zhouxiang $ rm *.c
linux@ubuntu:~/zhouxiang $ ls
linux@ubuntu:~/zhouxiang $ cd ..
linux@ubuntu:~ $ rm -r zhouxiang/
linux@ubuntu:~ $ ls
app Documents jeffy-vim-read proud test
demo Downloads Music Public Videos
Desktop hello.c Pictures Templates work
linux@ubuntu:~ $ mv test test01
linux@ubuntu:~ $ ls
app Documents jeffy-vim-read proud test01
demo Downloads Music Public Videos
Desktop hello.c Pictures Templates work
# 通配符: *
clear :清屏操作
13.sudo
功能:临时获取 root 用户权限
sudo 命名:以 root 用户的权限来执行命令
linux@ubuntu:~ $ sudo touch test.c # root 用户的权限创建 test.c 文件
[sudo] password for linux: # 密码是 1 ,输入不显示,直接回车确认
linux@ubuntu:~ $ ls -l
-rw-r--r-- 1 root root 0 Mar 20 22 :49 test.c
^
root 用户创建的
14.su
功能:切换用户
su 用户名
sudo su root :切换为 root 用户
linux@ubuntu:~ $ sudo su root
root@ubuntu:/home/linux #
^ ^ ^
1 2 3
1 .root 用户
2 . 当前所处的完整路径
3 . # root 用户权限
su linux :切换为普通用户
root@ubuntu:/home/linux # su linux
linux@ubuntu:~ $
root@ubuntu:/home/linux # exit
exit
linux@ubuntu:~ $
root 用户模式下, exit 退出 root 用户
在普通用户模式下, exit 关闭终端
15.chmod
功能:修改权限
drwxr-xr-x 2 linux linux 4096 Mar 20 20 :28 proud
rwx r-x r-x
r :可读 w :可写 x :可执行 - :没有对应的权限
文件属主(文件拥有者)、文件属组(同组用户)、其他用户
1 .
+ :添加权限 - :删除权限
u user ):文件属主(文件拥有者)
g group ):文件属组(同组用户)
o other ):其他用户
a all ):所有用户
sudo chmod 用户 + - 权限 文件名:修改文件权限
sudo chmod 用户 + - 权限 文件名 -R :修改目录文件权限
linux@ubuntu:~ $ sudo chmod a + w proud -R
[sudo] password for linux:
linux@ubuntu:~ $ ls -l
drwxrwxrwx 2 linux linux 4096 Mar 20 20 :28 proud
linux@ubuntu:~ $ sudo chmod u + x hello.c
linux@ubuntu:~ $ ls -l
-rwxr--r-- 1 linux linux 0 Mar 20 19 :33 hello.c
linux@ubuntu:~ $ sudo chmod o-w proud -R
linux@ubuntu:~ $ ls -l
drwxrwxr-x 2 linux linux 4096 Mar 20 20 :28 proud
16.apt-get
功能:软件包管理器
sudo apt-get install 软件名:下载软件
sudo apt-get remove 软件名:卸载软件
sudo apt-get upgrade :更新系统里所有软件
sudo apt-get update :更新下载列表
ping www.baidu.com
Ctrl + C :结束这个进程
ifconfig:查看主机IP地址 sudo ifconfig ens33 192.168.1.66 #修改主机IP地址为192.168.1.66
vi/vim编辑器
vim 文件名:文件不存在,创建文件并进入编辑;文件存在,直接进入编辑
刚进入处于命令模式,输入i进入插入模式
I:在行首进入
a:光标后一个字符出进入
A:在行尾进入
o:光标下一行进入
O:光标上一行进入
输入完成后,按Esc键退出到命令模式 在命令模式输入
:wq #保存并退出
:w #保存
:q! #强制退出 命令模式下的指令
yy:复制光标所处的一行
nyy:n为数字,复制光标所处那行开始往下n行
p:粘贴至光标下一行 P(大写):粘贴至光标上一行
dd:剪切光标所处的一行
ndd:n为数字,剪切光标所处那行开始往下n行
u:撤销前一个操作
gg:移动到第一行 G:移动到最后一行
nG:移动到第n行
$:移动到行尾
0:移动到行首
ZZ:保存并退出

c语言基础

第一个C语言程序

#include <stdio.h>
int main()
{
    printf("hello world!\n");
    return 0;
}
#include    预处理命令
stdio.h     标准输入输出头文件
printf  输出括号内的字符串,字符串要用双引号括起来
\n      换行符
return 0    函数的返回值
每个语句结尾要加分号;

GCC编译器

gcc 可选项 源文件
  • gcc编译流程

可选项对应的语言
-c只编译不链接,生成目标文件 ".o"
-S只编译不汇编,生成汇编代码
-E只进行预编译,不做其他处理
-g在可执行程序中包含标准调试信息
-o file把输出文件输出到file里
-v打印出编译器内部编译各过程的命令行信息和编译器的版本

【1】预处理阶段

去掉注释,加载头文件,代替宏定义,条件编译

条件编译 需要文件:.c文件 生成产物:预处理文件(以.i结尾)

gcc -E [源文件] -o [目标文件]

实例:gcc -E hello.c -o hello.i

后缀名为”.i”的文件是经过预处理后的C原始程序。

【2】编译阶段

编译阶段的主要工作是把我们的源代码生成相应的汇编代码的过程。这个阶段花费的时间会比较长。它需要对我们的C语言进行语法和语义的分析,如果有语法错误,报错,并结束编译过程;如果没有语法错误。此外,还需要优化我们的代码把C的源程序转变为汇编代码。需要文件:.i文件 生成产物:汇编文件(以.s结尾)。

gcc -S [源文件] -o [目标文件]

实例:gcc -S hello.i -o hello.s

后缀名为”.s”的文件是汇编语言原始程序。

【3】汇编阶段

首先我们应该知道汇编代码(汇编指令)并不是机器能够执行的语言。我们还必须把汇编语言翻译成计算机能识别的机器语言,这个翻译的过程是在汇编阶段完成的。所以在这个阶段把汇编源文件通过汇编器生成目标文件(二进制机器语言)。

gcc -c [源文件] -o [目标文件]

实例:gcc -c hello.s -o hello.o

C 语言代码经过编译以后,并没有生成最终的可执行文件(.exe 文件),而是生成了一种叫做目标文件(Object File)的中间文件(或者说临时文件)。目标文件也是二进制形式的,它和可执行文件的格式是一样的。对于 Visual C++,目标文件的后缀是.obj;对于 GCC,目标文件的后缀是.o。

【4】链接阶段

把目标文件执行所依赖的所有二进制的其他目标文件及C的库文件都整合成一个可执行文件的过程 需要文件:.o文件及各种动态库或静态库 生成产物:可执行程序。

gcc [源文件] -o [目标文件]

实例:gcc hello.o -o hello

编译只是将我们自己写的代码变成了二进制形式,它还需要和系统组件(比如标准库、动态链接库等)

结合起来, 链接(Link)其实就是一个“打包”的过程,它将所有二进制形式的目标文件和系统组件组合成一个可执行文件。

linux@ubuntu:~/test_c$ gcc test01.c
linux@ubuntu:~/test_c$ ls
a.out  test01.c
linux@ubuntu:~/test_c$ ./a.out
hello world!
linux@ubuntu:~/test_c$ gcc test01.c -o test01
linux@ubuntu:~/test_c$ ls
a.out  test01  test01.c
linux@ubuntu:~/test_c$ ./test01
hello world!
linux@ubuntu:~/test_c$ gcc -E test01.c -o test01.i
linux@ubuntu:~/test_c$ ls
a.out  test01  test01.c  test01.i
linux@ubuntu:~/test_c$ gcc -S test01.i -o test01.s
linux@ubuntu:~/test_c$ ls
a.out  test01  test01.c  test01.i  test01.s
linux@ubuntu:~/test_c$ gcc -c test01.s -o test01.o
linux@ubuntu:~/test_c$ ls
a.out  test01  test01.c  test01.i  test01.o  test01.s
linux@ubuntu:~/test_c$ gcc test01.o -o hello
linux@ubuntu:~/test_c$ ls
a.out  hello  test01  test01.c  test01.i  test01.o  test01.s
linux@ubuntu:~/test_c$ ./hello
hello world!

printf打印不同颜色

在嵌入式开发,服务器开发中,经常用到printf,在项目比较大,或者打印信息比较多时,可以通过打印的字符串的颜色的不同来凸显重要信息。

格式如下:

printf("\033[字背景颜色;字体颜色;控制码m 字符串 \033[0m");

颜色代码:

字背景颜色范围: 40—47字颜色: 30—37
40: 黑30: 黑
41: 红31: 红
42: 绿32: 绿
43: 黄33: 黄
44: 蓝34: 蓝
45: 紫35: 紫
46: 深绿36: 深绿
47: 白色37: 白色

ANSI控制码:

\033[0m关闭所有属性
\033[1m设置高亮度
\033[4m下划线
\033[5m闪烁
\033[7m反显
\033[8m消隐
\033[30m -- \033[37m设置前景色
\033[40m -- \033[47m设置背景色
\033[nA光标上移n行
\03[nB光标下移n行
\033[nC光标右移n行
\033[nD光标左移n行
\033[y;xH设置光标位置
\033[2J清屏
\033[K清除从光标到行尾的内容
\033[s保存光标位置
\033[u恢复光标位置
\033[?25l隐藏光标
\33[?25h显示光标
vim命令模式下,gg=G:整理代码

注释

注释用于描述特定的命令、函数或程序,增强程序的可读性,是编写程序代码的人为了方便理解代码所写的文本,被注释的文本不会被执行(因为在预处理阶段被删除)。

  • 普通注释

    【1】行注释:使用 //, 注释一行
    
    【2】块注释:使用/* */,  注释一段,多行注释用 /* 开始,用 */ 结束(标准C语言)
  • 使用条件编译快速注释

当需要注释的代码量较多时,如果使用块注释(/* */)则会出现无法配对等情况 此时可以使用以下方法来快速注释一段代码:

#if 0 
​
    待注释代码…… 
​
#endif 

当需要取消这段注释时,只需将0改成1即可

#if 1 
​
    待注释代码…… 
​
#endif

C语言编码规范

  • 命名规范

【1】在所有命名中,都应使用标准的英文单词或缩写。

【2】所有命名都应遵循达意原则,即名称应含义清晰、明确。

【3】所有命名都不易过长,应控制在规定的最大长度以内,一般不超过32个字节。

  • 编码规范

【1】在一行代码内只写一条语句;

【2】在嵌套的函数块中使用一个TAB缩进;

【3】每行长度不应超过80个字符;

【4】一个函数建议不要超过200行代码;

【5】程序中结束符号;(分号)前面不要加空格;

【6】为程序添加适当的注释;

  • 代码要求

【1】代码格式清楚、层次分明;

【2】代码易于理解、可读性强;

【3】代码具有健壮性,且没有错误;

标识符与关键字

字符集

  • 英文字母:大小写26个,共52个;

  • 阿拉伯数字:0~9;

  • 下划线(_)与冒号(:);

  • 特殊符号。

运算符

  • 算术运算符:+、-、*、\、%、++、--

  • 关系运算符:<、>、>=、<=、==、!=

  • 逻辑运算符:&&、|| 、!

  • 位运算符:& | ~ ^ >> <<

  • 条件运算符:? :

  • 分隔符: () [] {} . , ;

标识符

用于标识变量名、符号常量名、函数名、类型名、文件名等的有效字符序列。

标识符的命名规则

  1. 标识符只能由字母、数字和下划线三种字符组成,且第一个字符必须为字母或下划线;

  2. C 语言中的标识符大小写敏感;

  3. 用户自定义的标识符不能与关键字同名。

关键字

基本数据类型

void:声明函数无返回值或无参数,声明无类型指针,显示丢弃运算结果。
​
char:字符型类型数据,属于整型数据的一种。
​
int:整型数据,表示范围通常为编译器指定的内存字节长。
​
float:单精度浮点型数据,属于浮点数据的一种。
​
double:双精度浮点型数据,属于浮点数据的一种。
​
//_Bool:布尔型(C99标准新增)
​
//_Complex:复数的基本类型(C99标准新增)
​
//_Imaginary:虚数,与复数基本类型相似,没有实部的纯虚数(C99标准新增)
​
//_Generic:提供重载的接口入口(C11标准新增)

类型修饰关键字

short:修饰int,短整型数据,可省略被修饰的int。
long:修饰int,长整型数据,可省略被修饰的int。
// long long:修饰int,超长整型数据,可省略被修饰的int。(C99标准新增)
signed:修饰整型数据,有符号数据类型。(C89标准新增)
unsigned:修饰整型数据,无符号数据类型。
// restrict:用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式。(C99标准新增)

复杂类型关键字

struct:结构体声明。
​
union:联合体声明。
​
enum:枚举声明。(C89标准新增)
​
typedef:声明类型别名。
​
sizeof:得到特定类型或特定类型变量的大小。
​
// inline:内联函数用于取代宏定义,会在任何调用它的地方展开。(C99标准新增)

存储级别关键字

auto:指定为自动变量,由编译器自动分配及释放。通常在栈上分配。与static相反。当变量未指定时默认为auto。
​
static:指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部。
​
register:指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数。
​
extern:指定对应变量为外部变量,即标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
​
const:指定变量不可被当前线程改变(但有可能被系统或其他线程改变)。(C89标准新增)
​
volatile:指定变量的值有可能会被系统或其他线程改变,强制编译器每次从内存中取得该变量的值,阻止编译器把该变量优化成寄存器变量。(C89标准新增)

流程控制关键字

  • 跳转结构

return:用在函数体中,返回特定值(如果是void类型,则不返回函数值)。
​
continue:结束当前循环,开始下一轮循环。
​
break:跳出当前循环或switch结构。
​
goto:无条件跳转语句。
  • 分支结构

if:条件语句,后面不需要放分号。
​
else:条件语句否定分支(必须与if连用)。
​
switch:开关语句(多重分支语句)。
​
case:开关语句中的分支标记,与switch连用。
​
default:开关语句中的“其他”分支,可选。
​
for:循环
​
while:循环

变量与常量

在程序的指示下,计算机可以做很多事儿:数值计算、名字排序、计算彗星轨道、准备邮寄列表等。要完成这些任务,程序需要使用数据,即承载信息的数字与字符。有些数据可以在程序使用前预先设定并在整个运行过程中没有变化,这个称为常量。另外的数据在程序运行过程中可能变化或被赋值,这称为变量。

变量

所谓变量是指在程序运行过程中其值可以改变的量。使用变量时必须“先定义,后使用”。

变量的定义

在程序中,用到的所有变量必须有一个名字作为标识,变量名由用户定义,它必须符合标识符的命名规则。

编译系统将大写字母和小写字母认为是两个不同的字符。 在选择变量名和其它标识符时,应注意做到"见名知意",即选有含意的英文单词 (或其缩写)作标识符。

数据类型 变量名称;

变量的初始化

在C语言中,未初始化的局部变量为乱码,因此使用之前需要事先给值

定义时初始化变量

int num=666;
=:赋值号

定义后初始化变量

int num;
num=666;

变量的实质

一个变量实质上代表了内存中某个存储单元。在程序中,变量a就是指用a命名的某个存储单元,用户对变量a进行操作就是对该存储单元进行操作;给变量a赋值,实质上就是把数据存如该变量所代表的存储单元中。

变量的地址

变量在内存中总占用几个连续的字节,开始字节的地址,就是变量的地址。

练习:交换两个变量的值

//中间变量
#include <stdio.h>
int main()
{
    int a=66;
    int b=88;
    int temp;
    temp=a;
    a=b;
    b=temp;
    printf("a=%d,b=%d\n",a,b);
    return 0;
}

常量

在程序执行过程中,其值不被改变的量。常量主要分为两类:

直接常量:直接引用的数字等;

字符常量 ‘A’ , ‘a’

整型常量 10 100 0b1101 0664 0xaf

实型常量 3.14 5.69

字符串常量 "hello world","100"

符号常量:使用标识符来代替一个数字(常见的:宏定义常量 和 常变量)

宏定义

#define 也是C语言预处理命令的一种,被称为宏定义指令

所谓宏定义,就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串。

每行#define都由3部分组成。

#define 宏名 替换体
//第一部分是#define指令本身。
//第二部分是选定的缩写,也称为宏。有些宏代表值,这些宏被称为类对象宏(object-like macro);C语言还有类函数宏(function-like macro)。宏的名字中不允许有空格,而且必须遵循C变量的命名规则。
//第三部分称为替换列表或替换体。一旦预处理器在程序中找到宏的实例后,就会用替换体代替该宏(也有例外)。从宏变成最终替换文本的过程称为宏展开(macro expansion)。

类对象宏(object-like macro不带参宏)

#define 宏名 宏值
#include <stdio.h>
#define NUM 10
#define SUM "hello"
#define A 'a'
int main(int argc, const char *argv[])
{
    printf("%d\n",NUM); //%d输出整型数据
    printf("%s\n",SUM); //%s输出字符串
    printf("%c\n",A);   //%c输出字符
    return 0;
}

类函数宏(带参数宏)

#define 宏名(参数列表) 宏值
#include <stdio.h>
#define PI 3
#define S(r) PI*r*r
​
int main(int argc, const char *argv[])
{
    int r=5;
    printf("S(r)=%d\n",S(r));
    return 0;
}

使用宏定义的优点:

  1. 给数值赋予一定含义,增强代码可读性

  2. 减少代码编写量

  3. 可以“一改全改”

//输入程序,对比以下两个宏定义的不同
#include <stdio.h>
#define FUN1(a,b) a*b
#define FUN2(a,b) (a)*(b)
int main()
{
    int a=2;
    int b=3;
    printf("%d\n",FUN1(a+b,b+a));
    printf("%d\n",FUN2(a+b,b+a));
    return 0;
}
FUN1    a+b*b+a
FUN2    (a+b)*(b+a)

常变量

变量值不可改变的量,使用const修饰

const int a = 10;   // 定义一个常变量
a = 9;              // 报错,a为const修饰不可改变。
#include <stdio.h>
int main()
{
    int a=10;
    const int b=20;
    printf("a=%d,b=%d\n",a,b);
    a=66;
    //b=88;
    printf("a=%d,b=%d\n",a,b);
    return 0;
}

注意:

const修饰后的变量会变成只读,因此无法再次赋值。因此初始化常变量需要在定义时直接赋值。

常变量与宏定义常量的区别:

宏定义常量是在预处理阶段,使用宏名来代替宏值。而常变量是在程序运行时,程序在内存分配的一个变量,只不过变量不允许再次赋值。

数据类型

整型

整型类型包括短整型(short int)、基本整型(int)、长整型(long int),它们又被分为有符号(signed)无符号(unsigned)两种。

  • 基本型:类型说明符为int:值必须是整数,可以是正的,负的或者是0;其取值范围依赖于计算机系统。

  • 短整型:类型说明符为short int或short,用于仅需小数值的场合以节省空间。

  • 长整型:类型说明符为long int或long,用于使用大数值的场合。

  • 无符号型:类型说明符为unsigned。无符号型又可与上述三种类型匹配而构成,只用于非负值的场合

    • 无符号基本型:类型说明符为unsigned int或unsigned。

    • 无符号短整型:类型说明符为unsigned short。

    • 无符号长整型:类型说明符为unsigned long。

整型长度

实际情况也确实如此, C 语言并没有严格规定 short、 int、 long 的长度,只做了宽泛的限制:

  • short 至少占用 2 个字节。

  • int 建议为一个机器字长。 32 位环境下机器字长为 4 字节, 64 位环境下机器字长为 8 字节。

  • short 的长度不能大于 int, long 的长度不能小于 int。

总结起来,它们的长度(所占字节数)关系为:

2 ≤ short ≤ int ≤ long

sizeof运算符

获取某个数据类型或变量的长度可以使用 sizeof 操作符,以字节为单位来计数。

对于sizeof(),其形式类似于函数,但本质是C语言的一个运算符,且对 sizeof() 的处理都是在编译阶段进行。

#include <stdio.h>
int main()
{
    printf("short=%d\n",sizeof(short));
    printf("int=%d\n",sizeof(int));
    printf("long int=%d\n",sizeof(long int));
    printf("unsigned int=%d\n",sizeof(unsigned int));
    printf("unsigned long=%d\n",sizeof(unsigned long int));
    return 0;
}
#include <stdio.h>
int main()
{
    int a=0;
    scanf("%d",&a);
    printf("a=%d\n",a);
    return 0;
}

整数型常量

在C语言中,整常数有二进制、八进制、十六进制和十进制四种。在程序中是根据前缀来区分各种进制数的

[1] 十进制

十进制整常数没有前缀。其数码为0~9,只要常数中不含小数点和指数的数编译器都会当作整数。

合法的表达方式:237、-568、65535、1627;

非法的表达方式:023 (不能有前导0)、23D (含有非十进制数码)。

[2] 八进制

八进制整常数必须以0开头,即以0作为八进制数的前缀。数码取值为0~7。

合法的表达方式:015(十进制为13)、0101(十进制为65)、0177777(十进制为65535);

非法的表达方式:256(无前缀0)、03A2(包含了非八进制数码)。

[3] 十六进制

十六进制整常数的前缀为0X或0x。其数码取值为0~9,A~F或a~f。

合法的表达方式:0X2A(十进制为42)、0XA0 (十进制为160)、0XFFFF (十进制为65535)

非法的表达方式:5A (无前缀0X)、0X3H (含有非十六进制数码)。

[4] 二进制

二进制由 0 和 1 两个数字组成,使用时必须以 0b 或 0B(不区分大小写)开头

合法的表达方式:0b101(换算成十进制5)、0b110010(换算成十进制50)、0B100001(换算成);

非法的表达方式:101010(无前缀0B,相当于十进制)0B410(含有非二进制数码)。

注意:

标准的 C 语言并不支持上面的二进制写法,只是有些编译器自己进行了扩展,才支持二进制数字。 换句话说,并不是所有的编译器都支持二进制数字,只有一部分编译器支持,并且跟编译器的版本有关系。

整数的显示方法

显示十进制整数

%hd、 %d、 %ld 以十进制、有符号的形式输出 short、 int、 long 类型的整数
​
%hu、 %u、 %lu 以十进制、无符号的形式输出 short、 int、 long 类型的整数

显示八进制整数

%ho、 %o、 %lo 以八进制、不带前缀、无符号的形式输出 short、 int、 long 类型的整数
​
%#ho、 %#o、 %#lo 以八进制、带前缀、无符号的形式输出 short、 int、 long 类型的整数

显示十六进制整数

以十六进制、不带前缀、无符号的形式输出 short、 int、 long 类型的整数。如果 x 小写,那么输出的十六进制数字也小写;如果 X 大写,那么输出的十六进制数字也大写。

%hx、 %x、 %lx
​
%hX、 %X、 %lX

以十六进制、带前缀、无符号的形式输出 short、 int、 long 类型的整数。如果 x 小写,那么输出的十六进制数字和前缀都小写;如果 X 大写,那么输出的十六进制数字和前缀都大写。

%#hx、 %#x、 %#lx
​
%#hX、 %#X、 %#lX

实型(浮点型)

单精度(float型)/ 双精度(double型)/ 长双精度型(long double)

浮点数的表现形式

[1] 小数形式

由数码0~ 9和小数点组成。例如 0.0、 75.0、 4.023、 0.27、 -937.198 等都是合法的小数

[2] 指数形式

例如 7.25×(10^2)、 0.0368×(10^5)、 100.22×(10^-2)、 -27.36×(10^-3) 等。

任何小数都可以用指数形式来表示。但是在书写时, C 语言中的指数形式和数学中的指数形式有所差异。

C 语言中小数的指数形式为:

aEn 或 aen

a 为尾数部分,是一个十进制数;n 为指数部分,是一个十进制整数;E 或 e 是固定的字符,用于分割尾数部分和指数部分。整个表达式等价于 a×(10^n)。例如:

2.1E5 = 2.1×(10^5),其中 2.1 是尾数, 5 是指数。
3.7E-2 = 3.7×(10^-2)其中 3.7 是尾数, -2 是指数。
0.5E7 = 0.5×(10^7),其中 0.5 是尾数, 7 是指数。

浮点数的输出格式

小数也可以使用 printf 函数输出,包括十进制形式和指数形式,它们对应的格式控制符分别是:

%f:输出十进制计数法的float和double数字;
%e:输出指数计数法的float和double数字;
%lf、%le:输出double类型的数字;
%Lf、%Le:输出long double类型的数字;
#include <stdio.h>
int main()
{
    float a=0.666;
    double b=123.0;
    long double c=0.7623e-2;
    printf("a=%e,a=%f\n"
          "b=%e,b=%f,b=%le,b=%lf\n"
          "c=%Lf,c=%Le\n",a,a,b,b,b,b,c,c);
    return 0;
}

字符型(char)

字符并不是任意写一个字符,程序都能识别。例如圆周率π在程序中是不能被识别的,只能使用系统的字符集中的字符,目前大部分系统采用美国信息交换标准代码ASCII码(American Standard Code for Information Interchange)字符集。基本ASCII码标准定义了128个字符,用七位二进制来编码,包括英文大写字母26个、小写字母26个、数字符号0~9十个,还有一些专用符号(如“:”、“!”、“%”)及控制符号(如换行、换页、回车等)。

符号符号符号
0空字符44,91[
32空格45-92\
33!46.93]
34"47/94^
35#48 ~ 570 ~ 995-
36$58:96`
37%59;97 ~ 122a ~ z
38&60<123{
39'61=124|
40(62>125}
41)63?126~
42*64@127DEL(Delete键)
43+65 ~ 90A ~ Z

字符变量

字符变量使用类型字符char定义的变量。char是英文character(字符)的缩写。字符变量实质上是的整型变量的一种,一般占用一个字节(8bit),由于它常用来存储字符。所以称为字符变量。当它用于存储字符常量时,实际上是将该字符的ASCII码值存储到内存单元。例如,char c = ‘?’

定义一个字符变量c并使初值为字符’?’。’?’的ASCII代码是63,系统把整数63赋给变量c

在输出字符变量的值时,可以选择以十进制整数形式输出,或以字符形式输出。如:

#include <stdio.h>
int main()
{
    char a,b;
    int c,d;
    a=c=65;
    b=d='A';
    printf("char a=%c,int c=%c\n",a,c);
    printf("char b=%d,int d=%d\n",b,d);
    return 0;
}

运算符和表达式

C语言中用于告诉程序执行特殊算术或逻辑操作的符号称为运算符,运算的对象称为操作数

运算符括号操作数连接起来的符合C语言语法规则的句子称为表达式。

运算分类

【1】根据结合操作数的数目分类:(一元/二元/三元)

单目运算符:即操作数只有1个的运算符 i++,++i

双目运算符:即操作数有2个的运算符 +-*/

三目运算符:即操作数有3个的运算符,只有一个( ?: )

【2】根据运算符的用途分类:

赋值运算符:如=及其扩展运算符

逻辑运算符:如&&(与)、||(或)、!(非)

算数运算符:如+ - * / %等

关系运算符:如> < >= <= == !=等

位运算符:如<< >>等

条件运算符:只有一个: ?:

逗号运算符:只有一个 , 用于分隔

运算结合方向

运算符有两种结合顺序:自左至右、自右至左

自左至右(左结合性):表示运算符的操作数是从左向右(先左再右)与运算符结合的,如加法+

例:3 + 5,即3加上5,先取3,再取+,再取5

自右至左(右结合性):表示运算符的操作数是从右向左(先右再左)与运算符结合的,如赋值=

例:a = 3,即先取数3,再给a赋值

运算符优先级

C语言中运算符有优先级,从高到低分为15级(不同书籍划分方式不同,级数不同,这里采用百度百科划分方式),1级优先级最高,15级最低。

说明:

同一优先级的运算符,结合次序由结合方向所决定。

例如:对于表达式”x – y + z”,由于”-”和”+”都是同一级别的优先级,而它们的结合方向是左结合性,因此先计算”x-y”

简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符

算数运算符

四则运算符和求模运算符

符号及含义:+(加) -(减) *(乘) /(除) %(取余)

数目:双目运算符

结合性:自左至右

优先级:+和-:4级。*和/和%:3级

使用方法:表达式 运算符 表达式。如:3+5 a-b等

注意:

① C语言中,若相除2个数都是整数,则计算/时只取商,余数部分被舍去。

② %的操作数必须是整数

#include <stdio.h>
int main()
{
    float a=5.0;
    int b=2;
    int c=5;
    printf("%.2f\n",a/b);
    //%.2f:输出小数点后两位
    printf("%d\n",c/b);
    //printf("%d\n",a%b);   编译不通过
    printf("%d\n",c%b);
    return 0;
}

正运算符和负运算符

符号及含义+(正数) -(负数)

数目:单目运算符

结合性:自右至左

优先级:2级

使用方法+ 表达式 或 - 表达式。如:

int a = 3;
printf("%d\n", -a); // 对a取负数,会输出-3

自增运算符和自减运算符

符号及含义:++(自增1) --(自减1)

数目:单目运算符

结合性:自左至右 或 自右至左(取决于运算符位置)

优先级:2级

使用方法:

自增;变量++ 或 ++变量。如a++ 或 ++a

自减:变量-- 或 --变量。如b-- 或 --b

注意:

① 自增或自减运算符仅用于变量,不能用于常量或表达式

② 注意++/--运算符与+/-(正数/负数运算符)是同等优先级。当这两个运算符一起使用时,是右结合性。

即--a++ <---等价于---> --(a++);

③ 自增或自减运算符可用在操作数之前,也可以放在其后,这两种用法稍有区别:

  • 运算符在操作数前时:

C语言在引用操作数之前那就先执行加1或减1

例如:j = ++i;其执行过程是,先将变量i+1,再将计算结果赋给j。

  • 运算符在操作数后时:

C语言先引用操作数的值,然后再进行加1或减1,

例如:j= i--;其执行过程是,先将变量i的值赋值给j;再执行将变量i-1。

关系运算符

符号及含义>(大于) <(小于) >=(大于等于) <=(小于等于) ==(判等) !=(不等)

数目:双目运算符

结合性:自左至右

优先级:> < >= <=:6级。==和!=:7级

使用方法:表达式 运算符 表达式。如3<5,a==7等

注意:

① 关系运算符的操作数可以是变量、常量和表达式

② 关系表达式的的值是一个逻辑值:关系成立,即为真,结果为1;关系不成立,即为假,结果为0

③ 注意区分判断两个表达式相等的运算符是==,与=(赋值运算符)

逻辑真值和逻辑假值在c里是如何表达的?

0表示逻辑假,如0、0.0、\0、NULL

非0表示逻辑真,而且非零不一定是整数,可以是任何类型

逻辑运算符

逻辑运算符用于,对包含关系运算符的表达式进行逻辑上的合并或取非。

符号及含义:&& (逻辑与) ||(逻辑或) !(逻辑非)

数目:! 为单目运算符,&&|| 为双目运算符

结合性:! 为自右至左,&&|| 为自左至右

优先级:!:2级、&&:11级、||:12级

使用方法:

&&和||:表达式 运算符 表达式。

如:a && b、a || b

!:!表达式。如 !a

注意:

逻辑与:当且仅当两个表达式都为真时,则计算结果为真。否则为假

逻辑或:当且仅当两个表达式都为假时,则计算结果为假。否则为真

逻辑非:当原表达式为真时,计算结果为假;当原表达式为假时,计算结果为真

④ 使用逻辑运算符的表达式结果为真或假;

条件运算符

符号及含义: ?: (判断?前表达式是否成立,若成立取:前表达式,否则取:后表达式)

数目:三目运算符(C语言中唯一的三目运算符)

结合性:自右至左

优先级:13级

使用方法表达式1 ? 表达式2 : 表达式3

先判断表达式1是否成立,若成立取表达式2,否则取表达式3。

条件运算符相当于小型的if-else表达式

#include <stdio.h>
int main()
{
    int a,b;
    scanf("%d%d",&a,&b);
    int m = (a>b)?a:b;
    printf("m=%d\n",m);
    return 0;
}

长度运算符

符号及含义:sizeof()(计算括号内数据类型或表达式的大小)

数目:

结合性:

优先级:2级

使用方法:sizeof(表达式) 或 sizeof(类型名)

sizeof()用于计算某类型或某表达式所占内存的大小,经常与结构体/数组等连同使用

逗号运算符

符号及含义: ,(连接多个表达式组成一个新的表达式,并将最后一个表达式的值作为整个逗号表达式的值

数目:未知

结合性:自左至右

优先级:15级(最低)

使用方法:表达式1, 表达式2, …, 表达式n

示例:

y = ((x=a+b),(b+c));

y 等于整个逗号表达式的值,就是表达式2的值,x是第一个表达式的值。

赋值运算符及复合赋值运算

符号及含义:=(赋值) +=(加后赋值) -=(减后赋值) *=(乘后赋值) /=(除后赋值) %=(取余后赋值) <<=(左移后赋值) >>=(右移后赋值) &=\(按位与后赋值) ^=(按位异或后赋值) |=(按位或后赋值)

数目:双目运算符(一次赋值)

结合性:自右至左

优先级:14级

使用方法:

一次赋值:待赋值 运算符 表达式。如a=3,a=5+4,a+=5等

多重赋值:将同一个值赋给多个变量的操作,如a=b=c=10。此时a,b,c都为10

注意:赋值表达式的值:被赋值变量的值,就是赋值表达式的值。

a+=1;
//a=a+1;
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值