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

前言:最近通过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

阅读更多
个人分类: OCW C/C++
想对作者说点什么? 我来说一句

Practical C Programming

2012年01月08日 10.58MB 下载

6.087 Practical Programming in C, lec7

jubincn jubincn

2011-10-27 09:53:33

阅读数:538

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭