因为看到别人的推荐,所以看完了C专家编程,感觉还是写的比较好,有些知识点是可以积累的,于是写下了这篇笔记。。。。。
1.数组为什么是从0开始的,这个主要是因为数组的下标代表的是偏移量,这个对编译器来说是比较重要的。
2.看下面一段代码:
#include <iostream>
using namespace std;
int main()
{
char *cp;
const char *ccp;
ccp=cp;//允许
cp=ccp;//编译不通过
return 0;
}
这里要满足C语言赋值的标准:左操作数所指向的类型必须具有右操作数所指类型的全部限定符。
由于左操作数ccp有限定符const而右操作数没有限定符const。
3.算术转换:
首先,任何类型的char或者short的操作数会被转换成int,任何类型的float都会被转化成double。其次,如果一个操作数是double,另外一个也会被转化成double,一个是long,另一个也转化成long,计算结果也是long。两个是int才会导致结果为int
4.申明使用static的作用就是把该数据的分配从堆栈区直接变成了数据区里面,所以在子程序调用结束后,变量的值依然存在。
5.typedef和define的区别:
#define peach int //没有结束符;
unsigend peach i;//正确
typedef int banana;//有结束符;
unsigned banana i;//错误
# define int_ptr int *
int_ptr chalk,cheese;//等同于 int * chalk,cheese;
#typedef int_p int *;
int_p chalk,cheese;//等同于 int * chalk,cheese;
6.定义一个指针,并不会为其分配长度,只是一个指针的长度,但是在定义时同时赋初值(赋初值只有在字符串的时候才可以在定义一个指针时赋初值)。
例如:float *a=3.14;//这是不允许,char *a="abcd";
7.动态链接和静态链接
静态链接方式:在程序执行之前完成所有的组装工作,生成一个可执行的目标文件(EXE文件)。
动态链接方式:在程序已经为了执行被装入内存之后完成链接工作,并且在内存中一般只保留该编译单元的一份拷贝。
静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib中的指令都被直接包含在最终生成的EXE文件中了。但是若使用DLL,该DLL不必被包含在最终的EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。
采用动态链接库的优点:(1)动态链接的可执行文件比静态链接的可执行文件更加节省内存;(2)DLL文件与EXE文件独立,只要输出接口不变,更换DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和可扩展性,所有动态链接,(动态链接到某个特定的函数库的可执行文件在运行时共享该文件库)。3)静态链接在编译时对链接库的顺序有很大的影响。
8.可执行文件在内存中是如何布局的:
代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存种的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是不可写的。
数据段:数据段用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量。
BSS段:BSS段包含了程序中未初始化全局变量,在内存中bss段全部置零。
堆(heap):堆是用于存放进程运行中被动态分配的内存段,它大小并不固定,可动态扩张或缩减。当进程调用malloc/new等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减),从堆中申请内存只能用new和malloc(realloc、calloc)。堆中的内容只能通过指针来找到。
栈:栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味这在数据段中存放变量)。除此以外在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也回被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上将我们可以把堆栈看成一个临时数据寄存、交换的内存区。
8.内存泄露:堆出现问题的两种常见情况:1,未释放不再使用的指针2.还在使用的指针被释放了
检查内存错误的方法:利用top分析当前内存和进程等一系列的指标
9.段错误:这个在写代码的时候,一不小心就会出现段错误。段错误的原因:1.解除引用一个包含非法值的指针。2,解除引用一个空指针(函数的调用,返回一个空指针,没有检查就使用)3.未得到权限进行访问 4.用完了堆栈和堆空间
free(p),p=null;(加上这一句)
10,用C语言实现有限个状态机使用的是函数指针 void (*state[max_states])();
11.为什么C语言把数组形参当作指针,因为数组的拷贝实在是太大了,而在调用时我们仅仅只是需要知道初始地址就可以了,这样可以加快速度
12.多维数组的传参:1.一个就是数组传数组,然后告诉除最左边的维数外的其余维数 2.把多维数组转化成指针数组,然后传给形参是一个多级指针。
13.指针数组和数组指针:
指针数组:char *a[];//由于运算级的关系,char *a[]==(char*)(a[]),这个是一个代表数组的内容存的是指针
数组指针:char (*a)[];//这是一个指针,只不过是存数组的指针
这个有点类似于函数指针和指针函数:
指针函数:char * p();//返回指针类型的函数,等同于char * p()=(char *) (p())
函数指针:int (*f) (int x); /* 声明一个函数指针 *///指向函数头地址的指针
f=func; /* 将func函数的首地址赋给指针f */