@pnck
2023-08-21T01:11:14.000000Z
字数 11029
阅读 4046
首先C语言是一种高级语言,同时它又非常接近底层,C的编译器是目前世界上能生成最接近汇编极限效率的编译器,学习C语言可以了解到很多现代编程语言的特性,同时又能对硬件机制产生一定概念。
C语言的「抽象[1]方式」较少,且没有对内存操作进行高级封装,这意味着开发者需要自行处理数据在内存中的传递,同时也意味着学习者能学习到大量数据与内存的细节,这对以后更高级更抽象语言的理解会很有帮助。
一般来说,一个合格的programer需要由内而外地了解程序世界的前世今生,C就是这样一个契机,尽管它门槛比较高,但跨上去之后也会成为一个比较高的平台。but ofcoz,初学者通常也只关注 语言本身 而不是它带来的其它什么意义,所以我们也会推荐web初学者去看html或者php,对于更注重算法而不是程序实现的py(比如数学生物等非计算机的专业)会先学习脚本(如python)或matlab.
首先请弄清编译器和IDE(集成环境)的区别。无论选择什么编译器/IDE,基本原则都是 越新越好,只需够用 。编译器常见的有GCC、clang和微软的C/C++编译器(msvc),前两者是开源世界(GNU/LLVM)产物,多见于各式各样的小型IDE,后者只会被附带于微软的Visual Studio(VS)
中。以前常说的VC或VC6
实际上也是Visual Studio 6.0
的一个套件(那时候各套件是分开卖的软件包/光盘)。GCC由于是开源的,所以更新比较快 飞快!,对于新的语言标准支持也比较及时,而微软的编译器……你就只能等它发布下一个VS
了。所以鉴于轻量时效的原则,推荐大家尽量选择GCC编译器的IDE。
好几年又过去了(本文的第一个版本在2014年创建),原先的推荐列表早已经过时了(如果你想看看以前的说法,在文末)。现在大家电脑的操作系统已经普遍更新到 Win11,Linux阵营也迎来了一大波强力支持(还有WSL),随着各大商业公司逐步对Linux产生重视,特别是对桌面环境产生重视,我们现在已经有更好的全平台IDE啦!以下是推荐IDE/编辑器的列表:
全平台
):来自伟大良心的 Jetbrains 公司的C/C++ IDE,地球上最专业的IDE生产商,选他们没错的!而且作为一个 收费商业软件 ,Jetbrains全家桶有针对学生的 免费使用 授权。只要学校提供.edu
邮箱,就可以一直免费使用。具体办法百度一下jetbrains 学生
就有相当多结果。但也有缺点,对系统要求比较高,Linux
,Mac
):微软出品的代码 编辑器。 不过它只是个 编辑器,并不是IDE,要生成可执行文件还需要不少命令,对于初学者来说有点难度,但未来技能储备足够以后会发现这是个相当不错的编辑器。如果真要用它学习C语言,推荐一下这个插件Linux
):也是一个编辑器
,亮点是插件众多速度较快,但称不称得上好用就见仁见智了,推荐度一般。Windows
):自从VS2015将以往的Express
版本升级到Community
版之后,免费的Community版已经完全能满足所有的日常代码需求,不必再到处找盗版激活码了。虽然登录微软账号可能有点看网速和运气,但一般不至于运气太坏。VS有个缺点是功能太多,上手会迷路(每年都有60%左右的人会被挡在安装和创建工程之外!)。知乎上的这个回答基本包含了运行起helloworld的全部关键点,需要安装的部件和创建C代码的步骤都在图上了。Linux
):qtcreator
是一个开发qt程序的IDE,当然也可以用它写非QT的普通程序,在新建项目的时候选择Non-Qt Project
(非QT项目)再选择Plain C Application
(简单C应用程序)即可。gcc命令行
以及makefile
和cmake
的编写方式还是相当重要的(还有vim/emacs的用法 __(:з」∠)_)。没有void main()这种写法!
VC6
可以不报错地编译(注意我的表述,我不会说它是正常的)void main()
,而早期绝大多数程序员都在用VC6
,并且编写教材或书本的人也一定在用VC6
,结果导致很多没有弄清这个问题的人把这个问题一代代地传播下去了。(int main(void)
和int main(int argc, char **argv)
,后一种也可以写成int main(int argc, char *argv[])
,两个写法等价。main()
,从程序入口到main()
函数,操作系统要在背后完成大量的准备工作。(比如调用CRT中的mainCRTStartup
(Windows)或libc(glibc)中的__libc_start_main
(Linux));如果main()
不返回一个值,在程序退出时调用main()
的准备函数将收不到返回值,这可能破坏栈平衡,甚至引发内存错误。int main(void)
.int main()
? int main()
.main
函数这种由系统来调用的函数,一般不可能传入错误的参数,写成int main()
还是int main(void)
都没有问题,但对于你自己定义的函数来说,由于foo()
能接收任意参数,所以也许能开发出某些奇妙的高级写法,但一般很少见,所以一般不作区分。C语言标准的演变参照知乎,对于各版细节无需知道太多,只要了解C89
是第一个正式的C标准就好了,在这个标准以前写成的C程序,被称为Legacy C
.
VC6
不支持任何版本
的C标准,哪怕C89
,这也是为什么 现在极不推荐用 大家一直对其嗤之以鼻。VC6
最新版的VS2013对于C99
已经能比较完善地支持,官方文档给出了目前的支持情况;本文简要列出了还不支持的features.
GCC4.5
版本已经能支持大部分的C99
特性,而GCC4.9
对C11
的部分特性也已支持,剩下多线程和带边界检查的安全版本函数
[2]尚未实现。
不过需要注意的一点是,在不对编译器指定使用的C标准时,GCC
默认采用自行扩展的GNU C
标准,在IDE中应该会有类似的设置。
C99
以后的新东西,C的新标准也大多是一些解决瑕疵的缝缝补补和对编译器现有扩展的一些接纳,网上都找不到一个能对比编译器支持程度的列表。如果查阅 msvc/clang/gcc 各自的文档还是能发现一些细节上的不同,不过等有能力发现它们的时候也已经早有能力认识它们,不再需要本文指引了。初学C语言,最喜欢写的代码可能是这样的:
#include <stdio.h>
main()
{int a,b,c;
scanf("%d%d",&a,&b);
c=a+b;printf("%d",c);
}
因为它比较短,所有的变量都只有一个字母,main函数只需要一个单词加括号,简单。
但是学着学着,你写的代码就会变成这样:
#include <stdio.h>
main()
{void func();int a,b,c=10,i,j,k;
char d='*',m[]={""},*n;
scanf("%d%d",&a,&b);
for(i=0;i<a;i++){if(b<c){m[i]=b;}
else {n=&d;scanf("%c",n);while(b>0){printf("%c",*n);
}}}//……抱歉编不下去了
我瞎编的过程中已经分不清哪个括号是哪一层的,那些变量有什么用是什么类型的了,别说你们自己编的时候 你们回过头修改程序的时候。
非常看重选手挖掘奇技淫巧的能力
,选手需要熟悉各种优化代码长度的方法,除了压缩空白,缩短变量名,还要对程序运行编译机制有大量的了解。举个例子,加减法你会写吧,请给一段计算a+b的代码,输入输出都在10以内
,看你写的能不能比这个[3]短?自己和别人都能很容易看懂
if(sum!=nInput) return FALSE;
不必看上下文就可能猜出这个程序一定有将什么输入与什么的和 比较的功能,也许是一个校验过程,也许是一个判断加减法计算的东西,八九不离十。但如果你写return x==n? 1:0
则既难看又意义不明。上面这种变量命名方法叫匈牙利命名法。当然严格按照这样的命名方法也会出问题,很多大型项目的代码规范文档不提倡这种命名方式。所以还是遵循唯一正确的标准:自己和别人都能很容易看懂
。
严格遵循代码缩进
常见的代码缩进有这种
#include <stdio.h>
int main(void)
{
char *pszHint="括号的下一行代码缩进";
if(1)
{
printf("大括号与上一行对齐,%s",pszHint);
}
}//这种格式多见于VS
和这种
#include <stdio.h>
int main(void){
char *pszHint="括号的下一行代码缩进";
if(1){
printf("左大括号放在一行结尾,%s",pszHint);
}
}//这种格式多见于其它IDE,结构比较紧凑
不管哪种风格,请记住一个要点,语句块的开始不要跟大括号放在同一行,这是为了能清晰分辨语句块的开始与结束,参见之前那个糟糕的例子,你连现在在哪层嵌套里都弄不清。
严格区分每个变量的作用域,不要随意定义或使用会跨界的变量
这个问题有点抽象,最直观的例子就是i
,这个特殊的变量名几乎已经成了for
的一部分,大部分的for
里用作指示循环次数的变量都是i
。结果就是,你很可能会写出
int i=0,j=0,k=0;
// scanf,printf,判断scanf进来的东西,etc..
for(i=0;i<10;i++)
{
// do sth.
// ...
for(j=0;j<i;j++)
{
// do other things
// 很多层for
for(i=0;i<k;i++) // oops,你忘记i用过了
{
// 你以为你写了一个普通的循环嵌套,但外层并不能循环起来
}
}
// 为什么中间的循环跳过了?!
}
远古C标准中,变量的定义必须写在一起,在所有其它语句之前(现在早已没这个限制了)。所以早期教材的例子中会早早地定义i
,然后各种输入输出加判断,然后才正式开始循环。初学在抄代码改代码的过程中经常会写出「里层循环改了外层i」这种bug。类似的问题在遇到指针时会更加严重:你可能会想不起来到底哪个函数修改了指针指向的内容,或者意识不到指针传给下个函数会发生意外的变化。有很多“莫名其妙弄不清”的问题跟指针超乎想象的作用范围有关。所以最好让需要的变量定义在最晚的时刻,尤其是,不要定义在用到它的那层大括号(即作用域)的外面。
You know little about c++.
C#
Java
JavaScript
D
Go
都能看到C的痕迹,但C++跟它们不一样的地方在于,你能写出一段既是C又是C++的程序并正常编译运行,其它语言并不这样。不如说C和C++都是「某种可编译运行的语言」的超集,这也是C++要「竭力保持兼容」的部分。这部分占C语言的比重挺大,但对C++来说大概……只有一半吧。std::list
可以把任意大小和类型的数据组织成链表,但C怎么实现?能写一个 struct List
并用它串联任意类型的数据吗? Eclipse
这个候选项,现在想找到这个词都难。2017
2019
分别更新过一次,平台居然没有历史发布版本的记录,有点不可理喻。
对于
Windows7及以
下的用户,可以选择CodeBlocks
>>Dev-cpp
>=最新版本的VS
>>C-Free
>VC6
,codebloks是一个比较新的开源项目,功能比较全也有汉化包,编译器也很新,强烈推荐,而devcpp和cfree已经很久不更新了,不过devcpp使用mingw的编译器,IDE旧了点就旧了点吧,不影响;CFree则连编译器也很久没更新了,兼容性也较差,已不太推荐,不过还是比好些。VS摆在中间的位置,因为实在太大了,而且会有60%使用VS入门的初学者被拦在创建工程 (!) 上。bug遍地的16年前的什么标准都不支持的又旧又破烂的VC6
对于
Windows8及以上
的用户,为避免麻烦请直接去下载VS2013
,Win8本来对旧软件的兼容做的就不好(纯64位内核),安装codeblocks的时候可能还会遇到环境变量的问题,不过如果你看到这个词心中有数,还是去下CodeBlocks,完全没头脑,请下VS,然后参照文末引用的文章来创建简单的C程序工程(需要翻译不?)如果你想学习Linux并想在Linux上写C,你已注定成为一个苦逼的指挥官(command-er),希望这点东西能帮助你快速打造一个还看得过去的vim. 所幸Codeblocks是跨平台的,意味着它也能在Linux下使用,当然你还可以选
Eclipse+CDT
,不过这么累赘的东西……还不如leafpad记事本手打了。Linux上学习C唯一优越的地方就是编译非常方便快速,不过调试会蛋疼死你……
Using Microsoft Visual Studio for Simple C Programs
To edit your C program:
From the main menu select File -> New -> Project
In the New Project window:
Under Project types, select Win32 - Win32 Console Application
Name your project, and specify a location for your project directory
Click 'OK', then 'next'
In the Application Wizard:
Select Console application
Select Empty project
Deselect Precompiled header
Once the project has been created, in the window on the left hand side you should see three folders:
Header Files
Resource Files
Source Files
Right-click on Source Files and Select Add-> New Item
Select Code, and give the file a name
The default here will be a file with a *.cpp extension (for a C++ file). After creating the file, save it as a *.c file.To compile and run:
Press the green play button.
By default, you will be running in debug mode and it will run your code and bring up the command window.
To prevent the command window from closing as soon as the program finishes execution, add the following line to the end of your main function:
getchar();
This library function waits for any input key, and will therefore keep your console window open until a key is pressed.