您的位置:首页 > 其它

6.087 Practical Programming in C, lec1:Introduction. Writing, compiling, and debugging C programs.

2011-10-12 23:08 423 查看
前言:最近通过MIT OCW的6.087 Practial Programming in C来复习C语言,对照了下6.087的课程设置与C Programming Language的章节结构,感觉两者的顺序差不多,但6.087为了使学习曲线更平滑,将一些比较难的内容分为两个或多个章节,并将难点放到后面,从而使学习过程更为轻松。这里是6.087的链接:http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-087-practical-programming-in-c-january-iap-2010/

Lec1 Introduction. Writing, compiling, and debugging C programs. Hello world.



C features:

• Few keywords

• Structures, unions – compound data types

• Pointers – memory, arrays

• External standard library – I/O, other facilities

• Compiles to native code

• Macro preprocessor

习惯了面向对象中类型的万能和强大,回到C中的类型不禁产生一种反蹼归真的感觉。一切皆是数,整型自不必说,字符也是数,字符串就是一串数,浮点数的内部表示应该也是用整型数字。除此之外,最重要的是万能的指针,也是数,而且可以进行指针运算。似乎可以从C看到图灵机的经典模型。
C语言提供了基本的控制指令:

statement group( {} )
desicion making( if-else )
conditional switch ( switch-case )
loop with termination at top( for, while)
loop with termination at bottom(do...while)
early loop exit( break )

C语言中函数的返回类型可以是:

basic types
unions
structures
pointers

C语言中最常见的变量是自动变量(automatic variable),这种变量在每次调用时就重新创建,存在于栈中。
C语言的变量作用域有三种:

局部变量,函数内可用
外部变量,但只在一个文件内可用
外部变量,整个程序都可用

Inherently unsafe:

• No range checking

• Limited type safety at compile time

• No type checking at runtim

与Java、C++等面向对象的语言相比,C语言中的类型比较弱,早期这些类型都是可以混合进行运算。我认为C中的类型是由编译器来控制,因此编译后类型信息就没什么作用了。而Java、C#这些运行在虚拟机中的语言,在运行时其类型信息仍保留在中间码中,可以发挥一定的作用,如反射机制。

Using GDB

Some useful commands:

• break linenumber – create breakpoint at specified line

• break file:linenumber – create breakpoint at line in file

• run – run program

• c – continue execution

• next – execute next line

• step – execute next line or step into function

• quit – quit gdb

• print expression – print current value of the specified expression

• help command – in-program help

GDB是用于调试C程序的,上面是GDB常用的命令,入门时记住这些命令就足够了。对于内存相关的调试,可以使用Valgrind。

.C文件的结构

/* Begin with comments about file contents */

Insert #include statements and preprocessor definitions

Function prototypes and variable declarations

Define main() function

{

Function body

}

Define other function

{

Function body

}

上面是一个标准C程序的结构,首先将所需的其它文件尤其是库文件包含进来,并进行宏定义。将进行预处理操作的宏放到文件的最前面是很自然的事情,将include命令放到最前面,应该是为了使编译器在开始编译程序时就获得相关库或文件的信息,放到前面也是很合理的。我觉得include放到最前面,接下来是宏定义这种方式比较好,因为include命令独立性最好,放到前面就不用理他了,如果将include放到宏与程序之间,会增大程序员需要控制的代码行数。

变量声明

• Must declare variables before use

• Variable declaration:

int n;

float phi;

• int - integer data type

• float - floating-point data type

• Many other types (more next lecture. . . )

变量在声明后系统并不会在内存中给其分配空间,我认为声明只有在编译期间才有作用,编译器内部有一个有关各个变量的表,记录变量名称和类型。这样在编译时就可以进行类型检查,从而提前发现错误。

变量初始化

• Uninitialized, variable assumes a default value

• Variables initialized via assignment operator:

n = 3;

• Can also initialize at declaration:

float phi = 1.6180339887;

• Can declare/initialize multiple variables at once:

int a, b, c = 0, d = 4;

我认为,当有操作符作用于自动变量时,自动变量才会进栈,如果不对栈中的变量显示赋值,那么这个变量的值就是分配给它的那段内存的值,一般会清0。

操作符的执行序

• Order of operations:

Operator Evaluation direction

+,- (sign) right-to-left

*,/,% left-to-right

+,- left-to-right

=,+=,-=,*=,/=,%= right-to-left

• Use parentheses to override order of evaluation

操作符的执行顺序一般都是从左至右,只有单目运算符、三目运算符和赋值运算符的运算顺序是从右至左。这种执行序的不同会对编译器的编写造成一定麻烦,但所有的二目运算符都是从左到右,其它的都是从右到左,这么理解的话倒也不是很难实现。

Fucntion prototypes

• Functions also must be declared before use

• Declaration called function prototype

• Function prototypes:

int factorial ( int ); or int factorial ( int n);

• Prototypes for many common functions in header files for

C Standard Library

• General form:

return_type function_name(arg1,arg2,...);

• Arguments: local variables, values passed from caller

• Return value: single value returned to caller when function exits

• void – signifies no return value/arguments

int rand(void);

函数在使用前也必须声明,一个完整的函数声明应该包括返回类型、函数名和参数列表,函数签名应该包括返回类型和参数列表中参数的个数,参数类表中参数的类型和顺序是否包含在函数签名中我不清楚。我认为C这种弱类型的语言不应该将类型作为函数签名的一部分,Java和C#这些强类型的语言倒是可以,但没有考证过。

C中void和NULL有很大的区别。void仅在声明时使用,内存中并没有void这么一个变量,而NULL则是一个用户定义的常量,可以作为返回值返回。

The Main() Function

• main(): entry point for C program

• Simplest version: no inputs, outputs 0 when successful, and nonzero to signal some error

int main(void);

• Two-argument form of main(): access command-line arguments

int main(int argc, char ∗∗argv);

• More on the char **argv notation later this week. . .

万事开头难,定义一个起点是困难的。main函数是C语言中的程序入口,是程序的起点。argc至少为1,因为函数名自身也是一个参数,即*argv。

Function Definitions

Function declaration

{

declare variables;

program statements;

}

• Must match prototype (if there is one)

• variable names don’t have to match

• no semicolon at end

• Curly braces define a block – region of code

• Variables declared in a block exist only in that block

• Variable declarations before any other statements

“Functions break large computing tasks into smaller ones, and enable people to build on waht others have done instead of starting over from scratch” --C Programming Language, 2nd edition.

上面是K&R中对函数的说明,函数的主要作用是封装和重用。有时候感觉C的风格很简洁,如果把函数看作返回类型的一个普通变量的话,C程序就是一堆数在进行计算。因为字符实际上也是数字,所有的变量本质上都是数字,所以其核心就是运算符对变量的计算,我认为。

函数中定义的变量是局部变量,只在函数内部使用。

More about strings

• Strings stored as character array

• Null-terminated (last character in array is ’\0’ null)

• Not written explicitly in string literals • Preprocessor macros begin with # character

#include <stdio.h>

• Special characters specified using \ (escape character):

• \\ – backslash, \’ – apostrophe, \” – quotation mark

• \b, \t, \r, \n – backspace, tab, carriage return, linefeed

• \ooo, \xhh – octal and hexadecimal ASCII character

codes, e.g. \x41 – ’A’, \060 – ’0’



C中并没有字符串这种类型,我想这是为了简洁,毕竟字符串本质上就是多个字符而已。C中的基本类型都可以方便的用一个数字表示,而字符串做不到这一点,我想这也是为什么C中不将字符串设为基本类型的一个重要原因。

Preprocessor Macros

• Preprocessor macros begin with # character

#include <stdio.h>

• #define can take arguments and be treated like a function

#define add3(x,y,z) (( x)+(y)+(z))

• parentheses ensure order of operations

• compiler performs inline replacement; not suitable for recursion

Conditional preprocessor macros

• #if , #ifdef, #ifndef, #else, # elif , #endif

conditional preprocessor macros, can control which lines are compiled

• evaluated before code itself is compiled, so conditions must be preprocessor defines or literals

• the gcc option -Dname=value sets a preprocessor define that can be used

• Used in header files to ensure declarations happen only once

• #pragma

preprocessor directive

• #error, #warning

trigger a custom compiler error/warning

• #undef msg

remove the definition of msg at compile time

C中宏的工作原理其实比较简单,尤其是使用最多的define,就是做个替换。但C中宏似乎也是容易出问题的地方,因为它是在编译器编译之前运行的,因此编译时很难发现宏的错误。我觉得在写程序时要少用宏,但因为很多源代码(如linux)中大量使用宏,因此对宏还是要有些了解,至少要读懂。

Summary

Topics covered:

• How to edit, compile, and debug C programs

• C programming fundamentals:

• comments

• preprocessor macros, including #include

• the main() function

• declaring and initializing variables, scope

• using puts() – calling a function and passing an argument

• returning from a function
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: