基础语法,格式
首先来看一个标准的HelloWorld程序(C)
#include<stdio.h>int main(){printf("Hello World!");return 0;}
在此我不介绍各个字符或者函数的作用,我想让你上下对比一下:比如这段错误到离谱的程序
#inculde {stdio。h}
int mian();
【
print:(“Hello World!”);
return0;
】
当然诸君肯定不会错得这么离谱(是吧?!)
….(今天听完课发现最基本的准者没有讲,这里补充一下:
对于每一个程序源码,你在目前阶段需要注意的是:
头文件包含#inculde<??.h>
main函数 int main()
函数体用大括号:{(左括号开始)
}(右括号结束)
每一条语句以分号结尾;
最好每次程序的最后都添加 return 0;
注意:函数,条件运算符后面没有分号!!!:
错误举例如下:
if(a==1);
//if()之后没有分号!
int main();
{
printf("Error");
}
但注意,函数声明是需要分号的,这个在后期你会清楚,但不要搞混:
int PrintFunction(int a,char b[]);
int PrintFunction(int a,char b[])
{
//或者你可以这样理解,如果函数后面包含函数体部分{},则函数不需要分号
}
Part(01)-英文编码
请在书写代码时使用英文编码,最好关闭你的中文输入法或将输入法切换为英文模式!
这是新手最常犯错误之一(
编译器可没那么聪明,在编码中中文的分号”;”和英文的分号”;”是完全不同的!
同样,对于一些特殊符号,中文和英文有很大差异,编译器都 分!不!清!
后面会出教程教各位如何在编译器报错框定位问题,这里先提一下中文的报错大概长什么样:
比如,我”故意“把第7行的分号写成中文的分号(

//报错信息如下:
||=== Build file: "no target" in "no project" (compiler: unknown) ===|
C:\Probius_Code\TestC\test.c||In function 'main':|
C:\Probius_Code\TestC\test.c|7|error: stray '\243' in program|
C:\Probius_Code\TestC\test.c|7|error: stray '\273' in program|
C:\Probius_Code\TestC\test.c|7|error: expected ';' before 'for'|
||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
Part(02)-常规思维误区
比如:
A.if(a = 0)
B.if(a ==0)
如果你要判断a是不是等于b,如果按照平常思维来讲你可能会写出A的语法
但是在计算机中=是赋值符号,要判断相等要写作"=="
再看下面的例子:
现在你要完成一个函数的运算,这个函数是y=2x2+4x+8
或许你会这样写:
{
int x,y;
scanf("%d",x);
y=2pow(x,2)+4x+8;
}
那么恭喜你,你又犯错了~
首先:编译器无法将你想的“4x”识别为“4*x”
其次:变量前面不能带有数字——既然说到这,我们就简单提一下程序语言的命名规则:
1) 变量名的开头必须是字母或下划线,不能是数字。
2) 变量名中的字母是区分大小写的。比如 a 和 A 是不同的变量名,num 和 Num 也是不同的变量名。
3) 变量名绝对不可以是C语言关键字,这一点一定要记住!
4) 变量名中不能有空格。这个可以这样理解:因为上面我们说过,变量名是字母、数字、下划线的组合,没有空格这一项。
Part(03)-书写问题(误写,漏写
虽然这一点不怎么常犯,但是还是要提一下:
有一些函数,以及占位符的外形可能会很像,注意在学习的时候分辨,以及…
(不要用文字识别(OCR)抄代码…..)
If 和 lf确实挺像的((但正确写法是”lf”其大写为LF,而不是IF)
- #include
(欢迎各位来投稿问题hhhh)
码风
假的前言
其实是“代码规范”啦~
这里就用空梦酱的文章吧(我就懒得写了
但是我还是啰嗦几句,初学养成良好的代码写作习惯可以有效减少被开发组同僚杀掉或者工作被开除的可能性(逃
先引用一段短的(
1) 禁止取单个字母作为变量名(如 a、b、c、d、i、j、k、m、n……)。在前面的讲解中之所以用单个字母,只是为了方便讲解,以免喧宾夺主。刚开始学的时候也可以用,但是不要永远就只会用单个字母。
那为什么不要定义成单个字母呢?原因很简单——没有含义!你定义变量 a,其他人怎么知道这个 a 是什么意思?就算有注释,但难免会忘记。
所以在定义变量的时候,变量名最好要有明确的含义,这样可以提高代码的可读性。不管是自己写程序,还是别人读你的程序,都会很舒服。
在实际编程中经常用英文单词或英文单词的缩写来作为变量名,而且缩写也有一定要规则:
- 通常较短的单词可通过去掉“元音”形成缩写,比如表示“个数”的 count 可以缩写成 cnt;
- 较长的单词可取单词中的几个字母形成缩写;
- 对于一些单词还有大家公认的缩写,比如:
- temp 可缩写为 tmp; //temp是“临时”的意思
- flag 可缩写为 flg; //flag是“标志位”的意思
- statistic 可缩写为 stat; //statistic是“统计”的意思
- increment 可缩写为 inc;
- message 可缩写为 msg;
如果变量名由多个单词组成而且不用缩写,那么每个单词的首字母全部都要用大写,必要时可用下划线分隔。
2) 但并不是说就绝对不可以用单个字母,有些变量它本身就是没有含义,我们也不能硬生生给它赋予含义,这时候就可以用单个字母。比如后面学习循环语句的时候,里面有一个循环变量,它就是定义成 i、j、k,这已经是公认的了。
但大多数情况下,在编程的时候变量都是有含义的,这时候就应该用英文单词或英文单词的缩写作为它的名字。
….
以下内容提供:空梦
原文地址:https://blog.emptydreams.xyz/c_standard/
前言
在编写程序的过程中如果不遵守编译器的规定,编译器在编译时就会报错,这个规定叫作规则。但是有一种规定,它是一种约定成俗的规则,即使不按照那种规定也不会出错,这种规定就叫作规范。虽然在编写代码的过程中不遵守规范不会影响代码的运行结果,但会影响自己以及他人阅读代码,从而增加错误排查、理解代码的难度(极端例子可见我之前写的文章)。并且在未来步入职场的时候,不良的代码书写习惯也可能会使你丢掉一个工作。
代码规范写出来内容很多,可能有些人会抱怨:“这么多怎么记得住?!”。但实际上,代码规范并不需要背记。我们要首先理解代码规范的目的是什么?是让代码更整洁、更易懂。所以有些时候只要能保证代码整洁,就算不严格遵守代码规范依然没有问题。同时这也代表着我们不需要完全将规范背下来,只需要知道一些最基本的内容,然后加以练习、养成习惯,就能自然而然的写出整洁有效的代码。而日后再回顾以前的练习,你也会庆幸自己注意了这方面的内容。
正文
排版
缩进
如同写文章每个自然段前要加两个空格一般,写代码同样需要在一些部分添加空格来对齐代码。比如:
- 顶层元素不空格
- 每遇到一个{,下面的代码缩进就要多一段
- 如果一个字符串被拆成了多行,那么应该使用空格将字符串开头对齐
- 如果一行代码被拆成了多行,应添加空格表明这几行代码的包含关系
一段缩进一般为4格或者5格。同时应避免使用制表符(tab)进行缩进,因为使用制表符在不同的编辑器中显示效果可能不同(如果你的IDE会将tab键自动转换为空格进行缩进可以无视这个)。
每个函数前后加空行
unsigned int mult(int start, int end) {
unsigned int result = 1;
for (int i = start; i <= end; ++i) {
result *= i;
}
return result;
}
同一个函数中功能差别较大的代码块之间添加空行
比如上面几行代码完成的是一个功能,下面几行代码完成的是另一个功能,那么它们中间就要加空行。这样看起来更清晰。因为C语言的例子我没有找到,这里拿Java写的一个例子来充个数。
集中的变量声明后添加空行
如果你把函数中的变量全部写到了函数头(数量较多),那么应在声明后添加空行,如果数量不多可以不添加空行。
int amount, //...
year, //...
month, //...
day, //...
min, //...
wula, //...
oula, //...
muda; //...
//do something
善用空格
除.、!、~、++、—、’(‘、’[‘、->等与前(或后)文密切相关的操作符外,所有操作符前后都应添加空格,同时关键字后也应添加空格。
注意:一个空格足矣,不要连续敲一堆空格(除非你在对齐代码)。
int sum = a + b;
bool canPrint = sum > 0;
bool continueRun = sum >= 10;
if (canPaint) printf("%d", sum);
if (!continueRun) return false;
一条语句不要过长
某些情况下我们可能需要写一行非常长的代码(比如包含超长字符串),这时候我们应当将这一行代码拆分为多行,避免代码长度超过屏幕显示宽度。一般情况下代码宽度标准为80,读者也可根据自己屏幕的宽度适当增加这个宽度。
printf("乌拉乌拉阿斯蒂芬卢卡斯的的规划区内我发噶卫生间而她却尔雅如附件阿斯顿佛为日投标文件拷入按时灯笼裤能否勾起我i而后体哦我石达开你发给i哦请问然后那天给他");
//这里上下两段代码效果是一样的,显然后者更加符合规范
printf("乌拉乌拉阿斯蒂芬卢卡斯的的规划区内我发噶卫生间"
"而她却尔雅如附件阿斯顿佛为日投标文件拷入按时灯笼裤能否"
"勾起我i而后体哦我石达开你发给i哦请问然后那天给他");
一行仅包含一个变量声明(特殊情况例外)
正常情况下,一行仅包含一条变量声明,这样子也方便为变量添加注释。
double pi = 3.1415; //π
int r; //原半径
int c; //周长
int s; //面积
控制语句语句独占一行
正常情况下,if 、for 、 while 、case 、switch 、default 等语句独自占用一行,但如果后续代码非常短也可以共同占用一行。
//变量赋值这里省略
int min;
bool con;
switch (min) {
case 0:
//do something...
break;
case 1:
for (int i = 0; i < min; ++i) {
//do something...
}
break;
case 2:
while (min != 0) {
//do something...
}
break;
case 3: return 0;
default: return con ? 1 : 2;
}
大括号的位置
大括号书写的位置有两种写法,读者选择一种使用即可,不要多种混用。
//第一种
int main() {
}
//第二种
int main()
{
}
函数
一个函数不要过长
一个函数的行数尽量维持在50(或80)以下(非空非注释行)。
但有些函数例外,这些函数可能集成了非常庞大的单个功能,同时由于算法的复杂性无法进行有效的拆分(即拆分可能使代码变得更加复杂难懂)。
重复的代码提取为一个函数
如果有一个功能在多个地方被使用,那么应该这个功能提炼成一个独立的函数,这样使用这个功能的时候直接调用这个函数就可以了,有效减少了重复代码。
一个函数仅对应一个功能
一个函数完成多个任务是书写代码的大忌,这样不仅会让函数命名变得复杂,同时会让函数的职责变得不明确,增大了后期维护、修改以及理解的难度。
对参数的合法性检查应有明确的规定
通常情况下,应当对输入函数的参数进行检查,避免出现意外的情况。但是谁检查是一个普遍存在的问题。有两个极端的情况:一是调用者与被调用者都检查了,二是调用者与被调用者都没有检查。前者虽不会带来运行结果错误,但会出现代码冗余、运行效率降低的情况,后者则可能会导致莫名其妙的问题出现。
故写代码时应明确规定默认情况下应由谁来对参数进行检查,例外的函数也应在注释中指明情况。
命名规范
标识符的命名规则历来是一个敏感话题,典型的命名风格如unix风格、windows风格等,从来无法达成共识。实际上,各种风格都有其优势也有其劣势,而且往往和个人的审美观有关。我们对标识符定义主要是为了让团队的代码看起来尽可能统一,有利于代码的后续阅读和修改,产品可以根据自己的实际需要指定命名风格,规范中不再做统一的规定。 摘自:https://blog.csdn.net/m0_38106923/article/details/105042594
大分类
一、驼峰式命名
第一个单词首字母小写,后面其他单词首字母大写(又称小驼峰式)。我在本文列出的所有代码均遵循该命名方式,这里就不单独举例了。
二、帕斯卡命名
和驼峰式命名类似,只不过将首字母小写改为了首字母大写(故也被称为大驼峰式),也不单独举例。
三、下划线命名
所有字母小写,每个单词之间使用单下划线隔开。(PS:这个命名方法的名字是我瞎取的。)
int data_list;
double sum_result;
四、匈牙利命名
该命名方法不推荐使用,因为其最终使得代码更加难懂,远离了规范的本意,如果想要了解请自行百度。
补充
常量命名方法
常量(包括枚举常量)命名建议同意采用全部字母大写,单词之间采用单下划线分割的命名格式。这样子有利于一眼识别出该字段指向一个常量。
#define PI_ROUNDED 3.1415926
函数命名
函数命名一般采用 动词 + 名词 的命名方式,因为函数大都是用来执行某一个动作的,没有动作的函数是无意义的。
double getPI();
int getData();
int max(int a, int b);
int min(int a, int b);
注意事项
- 除了头文件或编译开关等特殊定义,所有常量变量不要用下划线(不论几个)开头,因为下划线开头的常量都是一些内部的定义。
- 禁止使用单字节命名变量,但 允许 定义i 、j、k作为局部循环变量
- 不建议使用匈牙利命名法
- 全局变量应增加g前缀,静态变量应增加s
- 尽量避免名字中出现数字编号,除非逻辑上的确需要编号
- 除了常见的通用缩写以外,不使用单词缩写,不得使用汉语拼音
变量
一个变量对应一个用途
一个变量只用来表示一个特定功能,不能把一个变量作多种用途,即同一变量取值不同时,其代表的意义也不同。
尽量使用 const 定义代替宏
一下内容复制自:https://blog.csdn.net/m0_38106923/article/details/105042594
“尽量用编译器而不用预处理”,因为#define经常被认为好象不是语言本身的一部分。看下面的语句:#define ASPECT_RATIO 1.653
编译器会永远也看不到ASPECT_RATIO这个符号名,因为在源码进入编译器之前,它会被预处理程序去掉,于是ASPECT_RATIO不会加入到符号列表中。如果涉及到这个常量的代码在编译时报错,就会很令人费解,因为报错信息指的是1.653,而不是ASPECT_RATIO。如果ASPECT_RATIO不是在你自己写的头文件中定义的,你就会奇怪1.653是从哪里来的,甚至会花时间跟踪下去。这个问题也会出现在符号调试器中,因为同样地,你所写的符号名不会出现在符号列表中。
解决这个问题的方案很简单:不用预处理宏,定义一个常量:const double ASPECT_RATIO = 1.653;
表达式
函数调用不要作为另一个函数的参数使用
不要将一个函数的返回值当作另一个函数的参数,这样子既不利于调试和阅读,也有可能导致意想不到的运算结果,例如:
//该代码摘自:https://blog.csdn.net/m0_38106923/article/details/105042594
int g_var;
int fun1()
{
g_var += 10;
return g_var;
}
int fun2()
{
g_var += 100;
return g_var;
}
int main(int argc, char *argv[], char *envp[])
{
g_var = 1;
printf("func1: %d, func2: %d\n", fun1(), fun2());
g_var = 1;
printf("func2: %d, func1: %d\n", fun2(), fun1());
}
赋值语句不要写在if等语句中
永远不要将赋值语句写在if中,因为这样会导致后期错误排查时无法明确判断到底是写错了还是故意要在if里面给这个值赋值。
不要过分依赖运算符优先级
在一段代码中包含多许多运算符时,使用括号表明执行顺序,不要使用优先级确保执行顺序,否则会导致代码阅读困难,也很容易出错。
注释
学会书写优秀的代码
优秀的代码可以做到自解释,即不需要书写注释也能让人明白代码的含义。
不要过多的使用注释
注释的本意是帮助人理解代码,过多的注释会让代码变得杂乱无章,起到反作用。
注释的语言
注释使用何种语言并没有硬性要求,但是考虑到生活环境应该优先使用中文,不要为了撞壁写出自己都读不懂的英文注释。
注释的位置
注释应放在被注释目标的上方或右方,不要放到下方。
补充
编译器警告
尽量将编译器警告调到最高级别,这样你更容易发现自己代码的问题。
参考资料:
按参考程度排序,程度越深越靠前。
