一、C语言的基本结构
(1)、第一个C程序:hello world
配置部署好 vsCode 之后,就可以直接在上面写代码了,新建一个新的C程序文件,向屏幕输出一串字符 “Hello World!”
下面,从整体上来分析一下这个最简单的C语言程序,将这个最简程序的各个部分剖析清楚,明白我们写下的每一个字符的具体含义。
实例代码1:
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("hello world!\n");
return 0;
}
实例代码2:
#include <stdio.h>
extern int funcA(void);
extern int num;
int main(int argc, char const *argv[])
{
printf("hello world!\n");
funcA();
num = 200;
return 0;
}
int num = 100;
int funcA(void)
{
printf("hello my love!\n");
return 0;
}
(2)、第一个C程序结构解析
1、头文件
#include <stdio.h> // 告诉编译器在.h文件中(声明)有这么一个符号,你需要去其相应的.c文件里去找其源文件(实现(定义))
- C语言程序中,任何符号(包括变量和函数)的使用,都是需要提前声明的。
- 如果程序用到了系统库函数,那么就需要包含相应的系统头文件来进行声明。
上述代码中用到库函数printf,而这个函数的声明在头文件 stdio.h 中,因此在该程序中需要包含此头文件。
声明:
- 概念:对源文件外定义的某个符号进行描述的过程,称为声明
- 作用:经过声明的符号,编译器才能正确识别和编译,否则编译器不认识,无法判定语法错误
- 符号:变量、函数等
- 示例:
// 声明一个变量符号number extern int number ; // 声明一个函数符号function extern void function(int size, char *buf); // 注意:前面的extern的关键字是可以不加的,但是建议初学者一定要加
2、主函数
- 主函数是必须有的,每一个C语言程序都有main函数,哪怕是空的。
- 主函数的名字是固定的,叫 main ,这个函数名不可被挪作他用。
- 主函数是程序的入口,也就是程序开始运行的地方。
- 主函数分解如下:
// int: 返回值类型,代表主函数最终的执行结果是一个整型数据 // main: main是函数名,这个名字不能变 // void: 是函数参数列表,可以省略,表示空的意思,就是没有参数的意思 int main(void) { ........ }
在 Linux 环境下,主函数 main 根据程序最终是否需要接收外部命令行参数,实际上有两个版本:
// 不接收外部命令行参数的版本 int main(void) { ... } // 接收外部命令行参数的版本 int main(int argc, char const *argv[]) { ... }
3、printf函数(标准输出 --- 屏幕设备)
C语言被称为是一种面向过程的模块化语言,所谓的模块,指得是一个个功能明确、各司其职的封装函数,它们就像一块块积木,被合理有机地拼搭起来,形成复杂、健壮的程序。
在这之中,系统标准C库提供了非常多“模块”,printf 就是其中之一,它的功能就是:向终端输出一段指定格式的数据。
面向对象:我干什么
面向过程:干什么
// 向终端屏幕输出一段字符串
printf("Hello World!\n");
解析:
a、常见的格式控制符:
一、基础格式控制:
%d // 十进制整数,decimalism
%o // 八进制整数,octonary
%x // 十六进制整数,hexadecimal
%c // 字符,character
%s // 字符串,character string
%f // 单精度浮点数,float
%p // 输出地址、输出指针的值,pointer
二、格式控制拓展(后面讲):
.........
示例代码:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int num = 100; // 定义一个整型类型的num变量,并给其赋初始值为100
char buf[128] = "out of love"; // 定义一个char型数组(char*类型),里面存放了一串字符
float f1 = 3.14; // 定义了一个单精度浮点型的变量,并给其赋初始值为3.14
double f2 = 3.14; // 定义了一个双精度浮点型的变量,并给其赋初始值为3.14
// 1、没有格式控制符的printf函数
printf("hello world!\n");
// 2、打印整型数
printf("整型数 = %d\n", num); // 要求打印num这个变量的时候,用十进制数表示:decimalism
// 3、打印八进制数
printf("八进制数 = %o\n", num); // 要求打印num这个变量的时候,用八进制数表示:octonary
// 4、打印十六进制数
printf("十六进制数 = %x\n", num); // 要求打印num这个变量的时候,用十六进制数表示:hexadecimal
// 5、打印字符(本质上是一个整型)
printf("字符 = %c\n", num); // 要求打印num这个变量的时候,用字符表示:character
/*
一开始计算机中是没有固定的数据(1010....)来表示字符的(abcdefg.....)
所以后面定了一个标准:ASCLL表(这个表描述了相关字符(128个字符)对应的数据(0-127))
*/
// 6、打印字符串
printf("buf = %s\n", buf); // 要求打印buf这个变量的时候,用字符串类型(数组类型)(char*指针类型)表示:character string
/*
printf("字符串 = %s\n", num);
因为num变量不是字符串类型的,所以会发生类型不匹配的情况
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("字符串 = %s\n", num);
格式%s要求参数类型为char *类型,但是printf函数的参数2的类型却是int类型
*/
// 7、打印小数(单精度浮点型)
printf("小数(单精度) = %f\n", f1); // 要求打印f1这个变量的时候,用单精度浮点型表示:float
// 8、打印小数(双精度浮点型)
printf("小数(双精度) = %f\n", f2); // 要求打印f2这个变量的时候,用双精度浮点型表示:double float
/*
题:
判断两个浮点型数据f1和f2的值是否一致
if( f1 == f2)
{
printf("两个浮点型数据相等\n");
}
else
{
printf("两个浮点型数据不相等\n");
}
*/
// 9、打印地址数据(打印指针变量里面的数据(指针变量里面的数据就是地址))
printf("num = %p\n", num); // (假地址:0x64(本质上是值))已地址的形式,打印出num的值(地址使用十六进制数据来表示的)
printf("num = %p\n", &num); // (真地址:0x7fff1d41d610)打印num变量的地址
return 0;
}
b、常见转义字符、显示特效转义字符:
转义字符通常前面有\符号
一、基本转义字符
\n - 换行符。将光标移动到下一行的开始位置。
\t - 水平制表符。通常会将光标移动到下一个制表位。
\\ - 反斜杠。用来表示实际的反斜杠字符。
\' - 单引号。用来表示实际的单引号字符。
\" - 双引号。用来表示实际的双引号字符。
\? - 问号。虽然问号本身不需要转义,但在某些情况下为了防止与三字母序列混淆,可能会用到。
\a - 警报声。发出警报声。
\b - 退格。将光标向后移动一个字符的位置。
\f - 换页。跳转到下一页的开始位置。
\r - 回车。将光标移动到当前行的开始位置,但不换行。
\v - 垂直制表符。通常会将光标移动到下方的垂直制表位。
\ooo - 其中ooo是1到3位的八进制数
\xhh - 其中hh...是一个或多个十六进制数字。(\101 和 \x41 都代表大写字母 'A' 的ASCII码值65)
二、背景色、字体色显示转义字符
a、格式:\033[40-47;30-37m
b、说明:
40/30: 黑色(背景色/字体色)
41/31: 红色
42/32: 绿色
43/33: 黄色
44/34: 蓝色
45/35: 紫色
46/36: 深绿色
47/37: 白色
c、使用:
printf("\033[40;32m《学生信息管理系统》\n");
三、显示效果转义字符
\033[0m // 关闭特效
\033[1m // 高亮效果
\033[4m // 下划线效果
\033[5m // 闪烁效果(只有ubuntu18.04系统具备这个效果)
\033[7m // 反显(交换前景色和背景色)
\033[8m // 消隐(文本不可见)
四、光标设置
\033[2J // 清除屏幕
\033[x;yH // 定位光标(x:横轴坐标, y:纵轴坐标)
\033[yA // 上移光标(y是纵轴移动的位置)
\033[yB // 下移光标
\033[xC // 右移光标(x是横轴移动的位置)
\033[xD // 左移光标
\033[H // 复位光标
\033[?25l // 隐藏光标
\033[?25h // 显示光标
\033[u // 恢复光标位置
\033[s // 保存光标位置
\033[K // 清除从光标到行尾的内容
4、return语句
C语言中的关键字 return 的含义是结束一个函数,并返回某个数据(若有)。而具体到 main 函数中时,由于主函数 main 的结束同时也意味着整个程序的结束,因此在上述 Hello World 程序中 return 后整个程序就退出了。
int main(void)
{
... ...
// 一般而言,函数正常退出返回0,非正常退出返回非0
return 0;
}
一般而言,程序正常退出时,main函数返回值是0;当程序异常退出时,main函数返回值是非0。
注意,main函数的返回值是给上一级进程的,因此理论上讲在当前的单进程程序中,main函数的返回值究竟是多少都无所谓,因为根本没有去使用这个返回值,除非在多进程程序中,进程间才需要使用main函数的返回值来传递信息。
二、man帮助手册、在线文档的使用(第一手资料)
(1)、man手册(manual:手动的)
编程开发的过程中,需要使用众多的系统指令、各类函数库、系统调用、各类系统脚本文件等,这些种类繁多、功能各异的信息,可以通过统一的man手册来获取第一手资料(英文),man文档是帮助信息的权威通道,是大多数教程、书籍的知识来源。
由于 man 手册所需要罗列的帮助条目众多,因此 man 手册被妥善地分为9册,不同的帮助信息被放入对应的man分册中:
- 在ubuntu命令行中敲:
:man man
- man文档的九个分册:
-
- 可执行程序或Shell命令(默认已安装)
- 系统调用 (Linux内核自带的函数)
- 库函数 (外部的第三方函数)
- 特殊文件(通常出现在/dev目录下)
- 文件的特殊格式或协定(例如/etc/passwd的格式)
- 游戏
- 杂项(例如一些宏定义)
- 系统管理员命令(通常只能由管理员执行)
- 非标准内核例程
a、man手册的安装
在默认情况下,系统只安装第一册,其他的帮助信息一般需要用户自己手动安装,安装指令如下:
gec@ubuntu:~$ sudo apt install manpages
gec@ubuntu:~$ sudo apt install manpages-dev
b、man手册的查询
使用man手册查询命令、函数时,一般直接在man后面接上待查条目即可,但有时候会遇到同一个待查询的条目存在于多个man分册的情况,这就需要先罗列出该条目所在的分册信息,然后再根据需要去选择帮助文档的序号。
1、查询单一分册的条目:
gec@ubuntu:~$ man strcpy
2、查询存在于多个分册的条目:
# 先使用 -f 来查看有哪些分册包含了该条目
gec@ubuntu:~$ man -f printf
printf (1) - format and print data
printf (3) - print formatted output
# 根据需要,指定查询某一册帮助分册
gec@ubuntu:~$ man 3 printf
c、man手册的使用
#include <stdio.h>
#include <string.h> // 向编译器声明strlen这个函数,方便编译器后面遇到它的时候,进行跳转
/*
使用man手册,来查询一个strlen函数的使用方法
1、在ubuntu系统终端上敲命令:man -f strlen // 查看该函数的man手册有几册,选择相应的手册数进行查询
2、man 3 strlen // 阅读打开man手册文档
3、如何使用一个函数??
a、函数的作用(NAME)
strlen - calculate the length of a string // 计算字符串的长度
b、函数的头文件(SYNOPSIS)
#include <string.h>
c、函数原型解析(DESCRIPTION)
size_t strlen(const char *s);
参数一:要计算长度的字符串变量
The strlen() function calculates the length of the string s, excluding the terminating null byte ('\0').
// 翻译:这个strlen函数会计算s这个字符串的长度,但是不包括结束符\0
d、函数的返回值(RETURN VALUE)
返回字符串的字节数(这个字符串有多少个字符)
*/
int main(int argc, char const *argv[])
{
char buf[128] = "nihao"; // 创建128个字符空间大小的内存,并将字符串内容,给赋值进去
size_t len = strlen(buf); // 使用字符串函数strlen,去计算buf内存里面有几个字符(其中不包括\0字符)
printf("len = %lu\n", len); // 由于size_t是long unsigned int数据类型,所以此处的格式控制符应为lud(其中d省略)
return 0;
}
(2)、在线文档(C/C++)
https://zh.cppreference.com/w/%E9%A6%96%E9%A1%B5
三、代码风格规范
1、标识符命名规则(变量名、函数名等):
-
- 只能包含数字、字母以及下划线,不能包含其他任何特殊字符。
- 只能以字母或者下划线开头。
- 不能跟系统已有的关键字重名,也不能跟本命名空间(namespace)中具有相同作用域的其他标识符重名。
- 尽量能一望便知,做到顾名思义,避免使用无意义字符
通常的命名方式(推荐):
(1)、函数名的命名方法:
1、驼峰命名法: FangHuiQing // 一般在面向对象开发的时候多使用
2、下划线命名法: fang_hui_qing // 一般在面向过程开发的时候多使用
3、二合一法: Fang_HuiQing // LED_InitDev(), LED_CloseDev(), LED_OpenDev(); 前面的命名表示文件名(led.c),后面表示函数功能
(2)、变量名的命名方法:
下划线命名法(小写): int led_num; int led_flag; // 前面的名字,能够让我们知道这个变量是哪个功能或是哪个文件的变量,后面的名字可以让我们知道是什么样的功能
(3)、宏定义
下划线命名法(小写): #define LED_ON 1
2、缩进:凡是有代码块的地方都必须缩进,一对大括号 { } 代表一个代码块
3、空格:标点符号后面,一般加空格
4、空行:不同逻辑段落中间,一般加空行
5、排版的快捷方式
让代码块整体左移: 选中代码块+shift键+tab键
让代码块整体右移: 选中代码块+tab键
注释/解除注释: 选中代码块+ctrl+/
标签:main,函数,int,嵌入式,num,man,printf,C语言,预科 From: https://blog.csdn.net/weixin_63053154/article/details/145137229