c基础回顾

环境:

翻译环境:编译-->目标代码-->链接-->可执行程序                 编译(预处理器处理--->解析)

执行环境:实际执行代码。

 

文件名规定:

C源代码通常保存于.c扩展名命名的文件中。有#include指令包含到C源代码中的文件被称为头文件,通常具有扩展名.h

 

UNIX系统下的编译链接:

   1.编译并链接一个源文件c程序:    cc program.c      生成一个称为a.out的可执行程序。中间产生一个名为program.o的目标文件,链接后被删除。

   2.编译并链接多个C源文件:      cc main.c sort.c lookup.c       当编译的源文件超过一个时,目标文件不会被删除。

   3.编译一个C源文件,并与现存的目标文件链接:   cc main.o lookup.o sort.c

   4.编译单个c源文件,生成一个目标文件,以后再链接    cc -c program.c

   5.编译几个c源文件,每一个产生一个目标文件   cc -c  main.c sort.c lookup.c

   6.链接多个目标文件:  cc main.o sort.o lookup.o

执行:

          1.一个运行时堆栈(stack),用于存储函数的局部变量和返回地址。

          2.静态内存(static)   

 \? 书写连续问号是,防止被解释为三字母词    如 ??( 代表 [

\"  转义

\'  转义

\\  转义

\b退格键

\n换行符

\r回车符

\t 水平制表符

\v 垂直制表符

\ddd     表示1~3位八进制数字 

\xddd   表示1~3位十六进制数

 

书写规范:在函数的定义中,返回类型出现于独立的一行,而函数的名字则在下一行的起始处。

              while循环的循环体没有任何语句。单独一个分号,称为空语句。这个分号独占一行。

 

基本数据类型:整数、浮点型、指针、聚合类型(数组和结构)

                    枚举类型  enum  它的值为符号常量而不是字面值类型。 这种变量实际上已整型的方式存储。

                   声明指针变量时,制定其初始值。

                    char *message =“hello  world”;  这条语句把message声明为一个指向字符的指针,并用字符串常量中第一个字符的地址对该指针进行初始化。

                      等价于    char *message; message=“hello world”;

typedef机制:

                  允许为各种数据类型定义新名字。如typedef char *ptr_to_char;    ptr_to_char a;   两条语句声明a是一个指向字符的指针。

const关键字:

                  1.声明常量    

                  2.在函数中声明为const的形参在函数被调用时会得到实参的值。

                  3.修饰指针时,指针变量和它所指向的实体都可能称为常量。

代码 含义
int   *pi; 指向整型的指针

int   const  * pci;

指向整型常量的指针;可以修改指针的值,但不能修改他所指向的值。
int  * const cpi; 指向整型的常量指针;指针是常量,值无法修改,可修改所指向的值。
int   const   * const  cpci; 指针和所指向的值都是常量,都不可以修改。

#define  MaxNum   50 

 

预处理指令:

             #include<stdio.h>

             #include<stdlib.h>

             #include<string.h>

             #define   MAX_COLS 20

原型函数

             对函数只声明无定义(参数名字不是必须)

              void rearrange(char *output,char const *input,int n_column,int const columns[]);

             数组参数是以引用(reference)形式传递,即地址调用;标量和常量是按值传递的。

字符串     “hello”占6个字节的空间,分别是 h,e,l,l,o和null

printf函数     执行格式化的输出

                  printf(“Original input : %s\n”,input);

%d 以十进制形式打印一个整型值
%c 打印一个字符
%s 打印一个字符串
\n 换行

scanf函数   从标准输入读取字符并根据格式字符串对他们进行转换

                  scanf(“%d”,&columns[num]);           //标量参数的前面必须加一个“&”字符,如果是数组参数不需要加,但是数组参数中如果出现下标引用,必须加。

                   例子:读取正数数组

          while(num<max && scanf("%d",&columns[num])==1 && columns[num]>=0){

                     num+=1;

            }

getchar()函数   从标准输入读取一个字符并返回他的值。如果输入不再存在任何字符,函数就会返回常量EOF,用于提示文件的结尾。

                 while((ch = getchar())!=EOF && ch!=\n)          //EOF 是一个整数值    ch声明为整数

 

 

存储类型:

          有三个地方用于存储变量:普通内存、运行时堆栈、硬件寄存器。    

          变量的缺省存储类型取决于它的声明位置。1、凡是在任何代码块之外声明的变量总是存储于静态内存中,为静态变量。静态变量在程序运行之前创建,在程序整个执行期间始终存在。2、在代码块内部声明的变量的缺省存储类型是自动的变量,存储于堆栈中。在程序执行到声明自动变量的代码块时,自动变量才创建,程序执行流离开代码块是,自动变量自行销毁。再次执行该代码块时,这些自动变量在堆栈中的内存位置,有可能与原来的相同,也可能不同。当代码块再次执行时,值一般并不是上次执行时的值。3、在代码块内部声明的变量加上static,则转换为静态变量。在整个程序执行过程一直存在,但作用域只在该代码内部。函数的形式参数不能声明为静态,因为实参总是在堆栈中传递给函数,用于支持递归。4、关键字register声明自动变量,存储于硬件寄存器中。

           初始化:

                   静态变量的初始化:把可执行程序文件想要初始化的值放在当程序执行时变量将会使用的位置。不显示制定初始值,初始化为0。

                   动态变量的初始化:函数的局部变量在函数的每次调用中可能占据不同的位置。自动变量无缺省的初始值。

                                            声明变量的同时进行初始化和先声明后赋值无效率差别。

链接属性

                       external 、 internal、none

                       extern关键字和static关键字用于在声明中修改标示符的链接属性。

                       external链接属性的声明+static关键字----->internal 变成源文件私有

                      static只对缺省的链接属性为external的声明才有改变链接属性的效果。

static关键字

            1.用于函数定义时,或用于代码块之外的变量声明时:static关键字用于修改标示符的链接属性,从external-->internal,标识符的存储类型和作用域不受影响。

            2.用于代码块内部的声明:static关键字用于修改变量的存储类型,变为静态变量。在程序执行之前创建。

 external 关键字

           (全局实体)在非代码内部和非函数定义内部,在缺省的情况连接属性为external。

            如果一个代码块内部变量前面添加extern关键字,则变成全局变量。

 

 

流程图:

         菱形表示判断,方框表示需要执行的动作,箭头表示它们之间的控制流。

Switch语句:

         switch(expression){                       //其中expression语句必须是整型值

                       statement-list;

         }

操作符:  

         移位操作符:左移位<< , 右移位>>    操作数必须为整型类型

                          对于无符号移位操作都是逻辑移位!对于有符号移位操作,根据编译器决定是逻辑移位还是算术移位!(有符号的移位是不可移植的)

        位操作: &  |  ^   分别为与、或、非

         赋值:      a=x=y+3;     //认为a和x被赋值相同的值的说法错误!    因为x如果是字符型变量,y+3的值会被截,a为截取后的值。

                       例子:  char ch;

                                  while((ch=getchar()!=EOF))   //错误! getchar()返回的是一个整型值而不是字符值。在有符号字符集的机器上运行时,出问题。

         单目操作符:~:对整数类型的操作数进行求补操作

                          &:产生它的操作数地址。

                           *:间接访问操作符,与指针一起使用,用于访问指针所指向的值。

                          sizeof:判断它的操作数的类型长度,以字节为单位表示。

 

函数:

函数原型:

            所有的函数都应该具有原型,尤其是那些返回值不是整数的函数。

             无形参的函数原型    int * func(void);

传递给函数的标量参数————传值调用

传递给函数的数组参数————传址调用

例子:返回某个int型数据在数组中的位置的函数:

复制代码
 1 #include<stdio.h>
 2 int * find_int(int key, int array[], int length)
 3 {
 4     int i=0;
 5     for(i=0;i<length;i++){
 6         if(array[i])==key)
 7             return  &array[i];          // 返回的是指向该位置的指针
 8     }
 9      return null;                     //此处不要省略,更加规范
10 }
复制代码

c中进行数据交换的函数以及调用:

 函数:

复制代码
1 void swap(int *x ,int *y)
2 {
3      int temp;
4      temp = *x;
5      *x = *y;
6      *y = temp;    
7 }
复制代码

函数调用:   swap(&a , &b);

ADT(抽象数据类型)和黑盒:

c通过 设计和实现抽象数据类型 可以限制函数和 数据定义的作用域

抽象数据类型的基本思想 ----模块具有功能说明----模块所执行的任务和接口说明----模块的使用

模块的用户并不需要知道模块实现的任何细节,并且除了已经定义好的那些接口以外, 用户不能一任何方式访问模块。

 基本思想:限制对模块的访问是通过static关键字的合理使用实现的,他可以限制对那些并非接口的函数和数据的访问。

 

C指针 

1.不能简单地通过检查一个值的位来判断它的类型,必须要观察程序中这个值的使用方式。

2.指针的初始化是用&操作符完成的,用于产生操作数的内存地址。指针一定要不初始化,不然不能进行解引用。

3.通过一个指针访问它所指向的地址的过程,用 *表示间接访问或者解引用指针。

4.NUll指针,作为一个特殊的指针变量。对一个null指针进行解引用是非法的,故需要提前判断是否是null指针!

5.  指针:int *b = &a;        //b为指向整型的指针变量,b=&a ,b指向地址a;*b为地址a的内容。

6.指针的指针:int a=12; int *b=&a; int **c =&b;    //操作符自右向左的结合

表达式 相当的表达式
a 12
b &a
*b a ,12

c

&b

*c

b,&a
**c *b,a,12

 

7.指针表达式

                   char ch='a';

                   char *cp = &ch;

表达式
*cp++ 右值为*cp=‘a’,然后cp++(指针增加,指向下一个地址)
(*cp)++ 右值为*cp=‘a’,然后‘a’++=‘b’
*++cp 右值为cp++后的值,即cp指针指向的地址的下一个地址的值
++*++cp 右值为cp指针指向的地址的下一个地址的值+1
++*cp++ 右值为=‘a’+1=‘b’,然后cp++(指针增加,指向下一个地址)

                    例子:计算字符串长度,查找一组字符串中的某个字符(用到**)。(判断是否是最后一个字符用‘\0’判断)

8.指针运算          

               算数运算    1.    指针 +/- 整数    (指针每增加1,指针所指向的地址增加1*指针所指向类型的大小。)

                              2. 指针 - 指针  (只有当两个指针都指向同一个数组中的元素时)

                关系运算

                             (大于、小于,大于等于,小于等于) (前提是指向同一个数组中的元素)

                 注意:要回辨别指针是否越界,和指向为知值的指针

           如下用于清除一个数组中的所有元素

复制代码
#define N_VALUES  5
  float values[N_VALUES];
  float  *vp;
  for(vp=&values[0];vp<&values[N_VALUES];){
              *vp++=0;
}
复制代码

        同上代码功能相同

复制代码
#define N_VALUES  5
  float values[N_VALUES];
  float  *vp;
  for(vp=&values[N_VALUES];vp>&values[0];){
              *--vp=0;
}
复制代码
以下此种写法错误!!!
复制代码

#define N_VALUES  5
  float values[N_VALUES];
  float  *vp;
  for(vp=&values[N_VALUES];vp>=&values[0];vp--){
              *vp=0;
}
//数组第一个元素被清除后,vp还会执行--操作,这就使vp移到了数组的边界之外。小心!!
复制代码

 

               

 

posted @ 2015-05-05 10:05  douding1828  阅读(168)  评论(0)    收藏  举报