Linux C基本知识点总结

 

Linux C基本知识点总结

1、calloc(num,size)和 malloc(size)的区别

次要区别是:calloc带有两个参数,可以分配num块size大小的内存

而malloc则是分配一个size大小的内存,没有做到那么细致

主要区别:calloc函数分配内存空间会初始化内存但是malloc不会。

2、是使用const和define定义常量区别

(1)、define不能定义变量类型和不能取变量地址,const就可以了。编译器可以对后者进行类型安全检查,

而前者仅仅进行字符替换,没有类型安全检查,并且在字符替换过程中会产生一些意料不到的错误。

(2)、在需要从库中导入常量值时const很有用;或者其和指针一起使用;

或者其为一个通过索引值访问的常量数组。否则,const对于#define没有优势。

(3)、原因是因为在大多数情况下,你想要一个常量,而不是有const限定符的变量。

两者在C中不完全一样(原文是note remotely the same,不知道有没有犯错)

例如,变量作为静态存储周期对象的initializer的一部分是非法的,例如不可变长数组的大小(例如结构中一个数组的大小,或者C99前的任何数组)。

(4)、C中的const和C++的不同。在C中,const定义的常量和#define定义的常量不完全相同。#define是预处理器指令,

在编译前就会把所有#define定义的常量的名字全部替换为其值。const定义的常量等同于只读变量,值在链接时才会知道。

(我想,我之所以会有这个问题,是因为我直接学了C++而不是先学C,而C和C++中的const不一样。)

因此const定义的常量对于编译器就不是100%的常量,数组长度不能是const常量,只能是#define定义的常量。

条件编译的时候也只能使用#define定义的常量。

那么也不是每个常量都是表示数组大小的吧,剩下的常量为什么也是用#define定义的呢?以我naive的思维,估计是因为为了代码风格上的统一吧。

(5)那么在C++中为什么还有很多#define呢?那估计就是继承了C的习惯吧,或者为了兼容C吧……不过,如果是C++,建议使用const,而不是#define,来定义常量。

总结:在C语言中使用限定符const不是很有用,即使是在常数表达式里(必须在编译期间被求出)想使用一个已命名的值,使用const也不是很有用的。C迫使程序员在预处理器里使用# define。

有些集成化调试工具可以对const常量进行调试,但是不能对宏常量进行调试。在C++程序中一般只使用const常量而不是用#define。

3、gdb调试介绍

关于程序调试

============

1,语法错误,由gcc来检查

2,逻辑错误,由你来负责

   2.1 使用printf来确定出错的位置,逐个排查错误

   2.2 如果以上无法确定错误来源,而且错误是段错误Segmentatin fault(就是你的程序访问了非法的内存,比如使用了野指针)

       可以让gdb帮我们直接定位出现段错误的地方。

       A) 使用 -g编译待调试代码

 

       B) 去掉系统对core文件的大小限制:ulimit -c unlimited

       C) 重新让程序死一遍,产生一个core文件

       D) 使用 gdb来直接定位: gdb ./example  core  (注意:不是100%能解决问题,看运气)

   2.3 如果发生的不是段错误,或者用以上办法,gdb无法直接定位段错误的位置,那就只能单步调试

       gdb 可供使用的常用命令:

gdb debugme

list

       > list/l/l 10/l 2,30 (列出当前正在调试的代码)

       > breakpoint/b 20 (在第20行设置了一个断点)

       > b 20 if i>=100 (在第20行设置了一个条件断点)

       > b somefunction (在函数somefunction设置了一个断点)

       > run/r/r 123 abc (启动程序开始运行,可以带参)

       > print i/p i  (查看变量i当前的值)

       > display i  (持续跟踪变量 i变化)

       > backtrace full/bt full  (查看当前栈内存的详细细节)

       > whatis i (查看变量i的类型)

       > next/n (单步执行:函数调用将会被当做一步)

       > step/s (单步执行:将会进入函数调用内部)

       > continue/c (继续执行代码,直到遇到下一个断点,或者程序退出)

       > quit/q  (退出调试器gdb)

 

 

 

4、linux c内存分配的几种方式

(1)、从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量、static静态变量

(2)、在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

(3)、从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或者new申请任意多少的内存,程序员自己负责在何时使用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

5、关键字volatile有什么含义?并给出三个不同例子

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。精确地说,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

三个例子:

(1)、并行设备的硬件寄存器(如:状态寄存器)

(2)一个中断服务子程序中会访问到的非自动变量。(全局变量、静态变量)

(3)多线程应用中被几个任务共用的变量

6、linux中进程和线程的对比和区别

进程:正在运行的程序

线程:进程中的一条执行路径

调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位

并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行

拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源

系统开销:在创建或撤销进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤销线程时的开销。

 

7、程序、进程、线程

定义:

 程序只是一组指令的有序集合。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位;

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),一个线程可以创建和撤销另一个线程;

进程和程序区别和联系

程序只是一组指令的有序集合,它本身没有任何运行的含义,它只是一个静态的实体。而进程则不同,它是程序在某个数据集上的执行。进程是一个动态的实体,它有自己的生命周期。反映了一个程序在一定的数据集上运行的全部动态过程。一个程序至少有一个进程,一个进程至少有一个线程

进程与线程的区别和联系:

进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

 

  线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

  从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

  进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

  线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

  一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

8、static变量的三个作用

(1)、static全局变量限制了变量的作用域,作用域为当前文件,当前文件的所有函数都可以访问,其他文件不能。

(2)、static局部变量,变量的生存期贯穿程序的整个运行时间段,变量值默认是0,只初始化一次。

(3)、static函数(静态函数)只能被本文件调用。

9、inline内联函数

       内联函数其实是代码的复制,避免了函数调用的开销,通过牺牲内存来换取效率。如果函数内的代码少,建议使用内联函数。

 

展开阅读全文

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