• C语言基础总结


    本文为C语言基础知识的总结,并非教程,适合有基础的猿们进行复习之用。


    基础模块:

    • C语言规定标志符只能由字母、数字和下划线三种字符组成,且第一个字符必须是字母或者下划线
    • 通常把long定义为32位,把short定义为16位,int可以是32位也可以为16位,这都主要取决于机器字长
    • C语言的二维数组,如果在初始时可以给出数组的初始值,那么可以只给出第二维的长度而可以不写第一维的长度,这和让数组作为形参时只需要写第二维的大小是一个道理
    • 字符数组的结尾字符是''
    • 局部变量:局部变量本身没什么好说的,但如果用static修饰,那么它在当前函数被执行完后不会被释放,下次执行该函数时会使用上次运行完后它的值,且静态局部变量会自动赋初值为0或空串等。
    • static修饰全局变量时,可以保证该全局变量不能被其他文件访问。
    • 预处理命令的前面必须加一个“#”号
    • 任何表达式语句都是表达式加分号组成的(预处理命令不属于表达式语句,因此不需要加分号)
    • 如果调用函数中没有return语句,并不带回一个确定的用户需要的值(没有显示标出返回值的类型,连void也没写),函数不是不带回值,而只是不带回有用的值,带回一个不确定的值,因此说“C语言函数返回类型的默认定义类型是void”是错误的
    • 用字符串方式赋值比用字符逐个赋值要多占一个字节, 用于存放字符串结束标志'',注意:strlen()测试字符串长度的函数不包括''
    • do-while循环至少要执行一次循环语句
    • 如果函数定义出现在函数调用之前,可以不必加函数原型声明,函数原型声明格式如下(来自:https://zhidao.baidu.com/question/358939347.html)
      在这里插入图片描述
    • x’ 与“x”的区别:
      ‘x’是一个整数,其值是字母x在机器字符集中对应的数值(ascii码)
      “x”是一个包含一个字符以及一个结束符’’的字符数组

    进阶:

    • C程序是先由源文件经编译生成目标文件,然后经过连接生成可执行文件。
      源程序的扩展名为 .c ,目标程序的扩展名为 .obj , 可执行程序的扩展名为.exe
    • 可以用一个指针变量指向一个函数,然后通过该指针变量调用此函数
    • 枚举类型中的元素都具有一个整型值,关于枚举细节请参看:https://www.cnblogs.com/JCSU/articles/1299051.html
    • define语句与枚举的区别:
      define编译器不检查这种类型变量中存储的值是否为该枚举的有效值。枚举变量提供这种检查,因此枚举比define更具优势。
    • 下图来自: https://blog.csdn.net/persever/article/details/78927562 在这里插入图片描述

    经典问答(大都参考自其他网站,参考网址已在最下方注明):

    1、static(静态)变量有什么作用?

    ① static全局变量和普通全局变量相比的区别在于static全局变量只初始化一次,这样做的目的是为了防止在其他文件单元中被引用;
    ② static局部变量和普通局部变量的区别是static局部变量只被初始化一次,下一次的运算依据是上一次的结果值;
    ③ static函数与普通函数的区别在于作用域不一样,static函数只在一个源文件中有效,不能被其他源文件使用;
    ④ 对于所有对象(不仅仅是静态对象),初始化都只有一次,而由于静态变量具有“记忆”功能,初始化后,一直都没有被销毁,都会保存在内存区域中,所以不会再次初始化。(记住:初始化语句只执行一次);
    在这里插入图片描述

    2、const

    java中也有const,但是只是作为预留字而非关键字(也就是不能使用)。C语言的const修饰普通变量和java中的final是一回事。
    ① const定义的是常量,表示不可变
    ② 进行类型检查,使编译器对处理内容有更多的了解,消除了一些隐患
    ③ 提高了程序的效率。编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译器间的常量,没有了存储与读内存的操作,使得它的效率也很高
    const void *a
    这是定义了一个指针a,a可以指向任意类型的值,但它指向的值必须是常量。在这种情况下,我们不能修改被指向的对象,但可以使指针指向其他对象。
    void* const a
    这是定义了一个const指针a,a可以指向任意类型的值,但a是指向某个对象的常量指针。我们不能修改指针中存储的地址,但可以修改指针指向的对象。

    3、define和const的区别
    • 角度1:
      就定义常量说的话:
      const 定义的常数是变量 也带类型, #define 定义的只是个常数 不带类型。
    • 角度2:
      就起作用的阶段而言:
      define是在编译的预处理阶段起作用,而const是在 编译、运行的时候起作用。
    • 角度3:
      就起作用的方式而言:
      define只是简单的字符串替换,没有类型检查。而const有对应的数据类型,是要进行判断的,可以避免一些低级的错误。
    4、关于main函数
    • C++里面是不是所有的动作都是main()函数引起的,但是一个C语言程序总是从main()函数开始执行的
    • 对于C++程序而言,静态变量、全局变量、全局对象的分配早在main()函数之前已经完成。所以并不是所有的动作都是main()引起的,只是编译器是由main()开始执行的,main()只不过是一个约定的函数入口,在main()函数中的显示代码之前,会调用一个由编译器生成的_main()函数,而_main()函数会进行所有全局对象的构造及初始化工作。
    5、new/delete与malloc/free的区别是什么?

    malloc/free是C/C++语言的标准库函数,在C语言中需要头文件<stdlib.h>的支持,new/delete是C++的运算符。对于类的对象而言,malloc/free无法满足动态对象的要求,对象在创建的同时要自动执行构造函数,对象消亡的之前要自动执行析构函数,而malloc/free不在编译器控制权限之内,无法执行构造函数和析构函数。
    具体而言,new/delete和malloc/free的区别:

    1)new能够自动计算需要分配的内存空间,而malloc需要手工计算字节数。

    2)new和delete直接带具体类型的指针,malloc和free返回void的指针。

    3)new是类型安全的,而malloc不是。

    4)new一般由两步构成,分别是new操作和构造。new操作对应于malloc,但new操作可以重载,可以自定义内存分配策略,不做内存分配,甚至分配到非内存设备上,而malloc不行。

    5)new将调用构造函数,而malloc不能;delete将调用析构函数,而free不能。

    6)malloc/free需要库函数stdlib.h的支持,而new/delete不需要

    需要注意的是,有资源的申请,就有资源的释放,否则就会出现资源泄漏的问题,所以new/delete,malloc/free必须配对使用。而delete和free被调用后,内存不会立即收回,指针也不会指向空,delete或free仅仅是告诉操作系统,这一块内存被释放了,可以用做其他用途。但是,由于没有重新对这块内存进行写操作,所以内存中的变量数值并没有发生变化,出现野指针的情况。因此,释放完内存后,应该将指针指项置为空。

    6、指针和数组是否表示同一概念?

    主要表现在以下两方面的不同:

    1)修改内容不同。

    例如,char a[]=“hello”,可以通过去下标的方式对其进行修改,而对于char *p=“word”,此时p指向常量字符串,所以p[0]='x’是不允许的。

    2)所占字节数不同

    例如,char *p=“world”,p为指针,则sizeof§得到的是一个指针变量的字节数,而不是p所指的内存容量。

    char a[]=“hello world”;

    char *p=a;

    在32位机器上,sizeof(a)=12字节,而sizeof§=4字节。

    但要注意的是,当数组作为函数参数进行传递时,该数组自动退化为同类型的指针。

    7、野指针?空指针?
    • 野指针是指指向不可用内存的指针。任何指针变量在被创建时,不会自动成为NULL指针(空指针),其默认值是随机的,所以指针变量在创建的同时应当被初始化,或者将指针设置为NULL,或者让它指向合法的内存,而不应该放之不理,否则就会称为野指针。
    • 而同时由于指针被释放(free或delete)后,未能将其设置为NULL,也会导致该指针变为野指针。
    • 虽然free和delete把指针所指的内存给释放掉了,但它们并没有把指针本身释放掉,一般可以采用语句if(p!=NULL)进行防错处理,但是if语句却起不到作用,因为即使p不是NULL指针,它也不指向合法的内存块。第三种造成野指针的原因是指针操作超越了变量的作用范围。
    8、#include<filename.h>和#include"filename.h"有什么区别?

    对于#include<filename.h>,编译器先从标准库路径开始搜索filename.h,然后从本地目录搜索,使得系统文件调用较快。而对于#include"filename.h",编译器先从用户的工作路径开始搜索filename.h,后去寻找系统路径,使得自定义文件较快。

    9、C语言和C++中struct的区别
    • C语言的struct不能有函数成员,而C++的struct可以有
    • C语言的struct中数据成员没有private、public和protected访问权限的设定,而C++的struct成员有访问权限限定。
    • C语言的struct是没有继承关系的,而C++的struct有丰富的继承关系
    10、函数指针和指针函数的区别

    指针函数是指带指针的函数,本质上是一个函数,函数返回类型是某一类型的指针。其形式一般如下所示:

    类型标识符 *函数名(参数列表)
    

    例如,int * f(x,y),它的意思是声明一个函数f(x,y),该函数返回类型为int型指针

    而函数指针是指向函数的指针,即本质是一个指针变量,表示的是一个指针,它指向的是一个函数。其形式一般如下所示:

    类型说明符 (*函数名)(参数)
    

    例如,int (*pf)(int x)它的意思就是声明一个函数指针,而pf=func则是将func函数的首地址赋值给指针。


    关于C语言的指针,请看:https://blog.csdn.net/constantin_/article/details/79575638
    C语言中的指针和p, p+1, *(p+1), *P+1, p[0], &p[0] 的含义:https://blog.csdn.net/m0_37605407/article/details/79198118


    参考资料:

  • 相关阅读:
    5.4、获取对象信息
    5.3、继承和多态
    JS基础-组成
    js定时器
    js 原型链,继承,闭包,内存,泄露
    flex 布局
    点击导出table表格
    图片利用 new Image()预加载原理 和懒加载的实现原理
    js控制style样式
    自定义指令的用法
  • 原文地址:https://www.cnblogs.com/yinyoupoet/p/13287465.html
Copyright © 2020-2023  润新知