黑马程序员技术交流社区

标题: C语言基础知识要点回顾 [打印本页]

作者: yuanlingqi    时间: 2014-11-7 12:31
标题: C语言基础知识要点回顾
一、基础相关
1. #include 相当于导入文件内容。
2.main可以没有返回类型,没有参数,不写返回类型默认返回int,语法是不严格的。
3.C语言运行有两个步骤分别是,编译和链接,编译是将程序编译成目标代码,链接是将函数库的内容也加入到编译类,编译成功会生成.obj文件,链接完成后C程序才能执行。
4.C程序是从上往下执行,入口函数调用自定义方法必须要写在main之前或做声明。
  1. #include <stdio.h>

  2. int sum(int,int);
  3. int main(int argc, const char * argv[])
  4. {
  5.     sum(10,3);
  6.     return 0;
  7. }

  8. int sum(int a,int b){
  9.     return a+b;
  10. }
复制代码
5.
自定义函数通常写成.h和.c文件,类似一个是接口,一个是实现,main只需要包含.h文件即可,不可直接包含.c文件,会导致函数重复定义的错误:
  1. 5.1 main.c
  2. #include "firstC.h"
  3. int main(int argc, const char * argv[])
  4. {
  5.     printf("sum结果为%d",sum(10,3));
  6.     return 0;
  7. }
  8. 5.2firstC.c
  9. #include <stdio.h>
  10. int sum(int a,int b){
  11.     return a+b;
  12. }
  13. 5.2firstC.h
  14. #ifndef FirstC_firstC_h
  15. #define FirstC_firstC_h
  16. int sum(int a,int b);
  17. #endif
复制代码
6.
C语言的数据类型,大致归为四类,基本数据类型,空类型,指针,结构体类型。
注意:变量初始化的时候必须给默认值,否则会出现一个随机值,会引起不必要的异常。




作者: yuanlingqi    时间: 2014-11-7 12:36
二、指针相关
1.使用指针实现单个方法多个返回值:
  1. int sumAndMinus(int a,int b,int*p){
  2.     *p=b-a;
  3.     return a+b;
  4. }

  5. int main(int argc, const char * argv[])
  6. {
  7.     int a = 10;
  8.     int b = 20;
  9.     int minus;
  10.     int sum =      sumAndMinus(a,b,&minus);
  11.     printf("%d,%d",minus,sum);
  12. }
复制代码
2、在同个编译环境下,一个指针变量占用的内存空间是固定的。
3、指针和数组有共性也有区别,主要区别如下:
  1. char s[7]="iloveyo";//字符串变量
  2. char *p = "iloveyou";//字符串常量
复制代码



作者: yuanlingqi    时间: 2014-11-7 12:43
三、指向函数的指针
1.函数名就是函数地址
2.声明一个指向函数的指针变量
  1. int sumAndMinus(int a,int b,int*p){
  2.     *p=b-a;
  3.     return a+b;
  4. }

  5. int (*p)(int a,int b);
  6. p = sumAndMinus;
  7. (*p)(5,6);//等价于p(5,6);
复制代码
3.指向函数的指针的用途
代码不变,算法变动的情况下,需要用到指向函数的指针,可以将函数当做参数实现相应算法。
功能和Lambdas以及和oc中的block有点类似:
  1. int sum(int a,int b){
  2.     return a+b;
  3. }

  4. int minus(int a,int b){
  5.     return a-b;
  6. }

  7. int caculate(int a,int b,int (*p)(int,int)){
  8.     return p(a,b);
  9. }

  10. int main(int argc, const char * argv[])
  11. {
  12.     int sumResult = caculate(20,10,sum);
  13.     int minusResult = caculate(20,10,minus);
  14.     printf("sumResult=%d,minusResult=%d",sumResult,minusResult);
  15. }
复制代码



作者: yuanlingqi    时间: 2014-11-7 12:49
四、预处理指令1. 预处理指令包括:宏定义,文件包含和条件编译:
1.1、宏定义
  1. //宏定义用来定义常量
  2. #define NUM 6
  3. //带参数的宏定义,简单的计算函数尽量用宏定义替代,效率更高
  4. #define mul(a,b) ((a)*(b))
  5. int main(int argc, const char * argv[])
  6. {
  7.     int mulResult = mul(20,10)/mul(2,2);

  8.     printf("mulResult=%d",mulResult);
  9. }
复制代码
1.2 条件编译:
  1. #define NUM 0
  2. int main(int argc, const char * argv[])
  3. {
  4. //    条件编译,效率更高
  5. #if NUM==0
  6.       printf("NUM == 0");
  7. #elif NUM > 0
  8.       printf("NUM > 0");
  9. #else
  10.       printf("NUM < 0");
  11. #endif
  12.     return 0;
  13. }
复制代码
根据宏来进行条件编译:
  1. //#define NUM 0
  2. int main(int argc, const char * argv[])
  3. {
  4. //如果定义过宏NUM则编译,否则编译另一段
  5. //#if defined(NUM)等价于下面的写法
  6. #ifdef NUM
  7.     printf("宏已经定义");
  8. #else
  9.     printf("宏未定义");
  10. #endif
  11.     return 0;
  12. }
复制代码
1.3 文件包含

避免重复包含很重要,系统自动帮我们实现了这个代码,它是利用条件编译和宏定义来实现的
//若宏未定义则定义该宏,并将文件包含进来,若已定义则不再包含该文件
#ifndef FirstC_firstC_h
#define FirstC_firstC_h
int sum1(int a,int b);
#endif


作者: 易拉罐    时间: 2014-11-7 12:51
路过,顺便也学习了一下。。

作者: yuanlingqi    时间: 2014-11-7 14:15
五、其他要点
1.变量的存储类型:
a.自动变量-堆栈-生命周期短-运行时局部变量
b.静态变量-普通内存-生命周期相对长-程序运行前创建全局变量和static修饰的局部变量(static改变的是生命周期,不变的是作用域)
c.寄存器变量-寄存器-被register修饰的自动变量称为寄存器变量-迅速创建迅速销毁,只限于int,char和指针类型变量


2.extern函数
外部函数:如果在当前文件定义的函数允许其他文件调用,访问,该函数就是外部函数,默认为外部函数,不允许重复同名。
内部函数:如果不允许其他文件调用访问,则称为内部函数。
//完整声明一个函数,需要用到extern关键字,表示引用一个外部函数,可以省略,默认就是
extern void test();
int main(int argc, const char * argv[])
{
    test();
    return 0;
}
用static 修饰的全局变量,就是内部变量,将无法被外部类访问。
作者: yuanlingqi    时间: 2014-11-7 14:35
六、其他一些要点笔记


1、指向结构体的指针,利用指针访问结构体成员,(*p).age等价于p->age
2、枚举类型,通常用来声明一组常量,枚举会被当做整数类型处理。
   
  1. enum season{spring,summer,autumn,winter};
  2.     enum season se=summer;
  3. 遍历枚举的方法
  4. for(se=spring;se<winter;se++)printf("%d\n",se);
复制代码
3、typedef给数据类型起别名重命名int类型
typedef int Integer;
重命名指针类型
typedef char* String;
//#define Integer int
重命名结构体
typedef struct Point{float x;float y} Mypoint;
    Mypoint pt={1.1,2.2};
    printf("%.2f,%.2f\n",pt.x,pt.y);
重命名结构体指针类型
typedef struct Point{float x;float y}* Mypoint;
    struct Point pt={1.1,2.2};
    Mypoint pt2 = &pt;
    printf("%.2f,%.2f\n",pt2->x,(*pt2).y);
通常会先重命名结构体类型,然后再重命名结构体指针类型
typedef struct {float x;float y}Point;
    typedef Point* MyPoint;
    Point pt={1.1,2.2};
    MyPoint pt2 = &pt;
    printf("%.2f,%.2f\n",pt2->x,(*pt2).y);
重命名枚举类型
typedef enum {spring,summer,autumn,winter} Season;
    Season ss = spring;
重命名指向函数的指针
typedef int (*mysum)(int,int);
    mysum pp = sumo;
    printf("%d\n",(*pp)(5,6));
4、typedef和宏定义的区别,宏定义仅仅是替换


作者: doudou33420    时间: 2014-11-7 14:35
支持一下 总结的很细
我对函数指针一直没什么理解,  感觉和直接使用函数没区别..  (作为参数传递?)
static 可以间接被外部访问(我是这么理解)
一个类定义了static全局变量  第二个类#import它   在第二个类中 就可以直接访问此变量并且可以给它赋值

作者: yuanlingqi    时间: 2014-11-7 15:17
doudou33420 发表于 2014-11-7 14:35
支持一下 总结的很细
我对函数指针一直没什么理解,  感觉和直接使用函数没区别..  (作为参数传递?)
static ...

若不是这几年流行一个概念叫函数编程,我也不会留意到函数指针,因为指向函数的指针,向来是不作为C语言基础内容的。你有兴趣可以了解下函数编程,目前是各大流行语言力捧的编程方式,未来会越来越重要。
作者: doudou33420    时间: 2014-11-7 15:19
  恩  放到以后研究
作者: breaking1800    时间: 2014-11-7 15:37
总结得很好啊!
作者: 飞奔的坦克    时间: 2014-11-7 21:21
不错。。。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2