--
分类: C/C++
2014-01-14 15:31:35
第一章、声明和初始化
1、如果可能很大(大于32767或小于-32767),就是用long,若空间很重要就short,否则就用int,C99中long long至少64位。
2、标准头文件
3、全局变量或函数多处声明,定义仅为一次,若想多个源文件共享变量或函数,最好在*.c中定义,*.h中进行外部声明。其他只需要包含对应头文件即可。
4、最好使用typedef,不要使用#define,因为处理指针的时候不会出错。且遵循作用域优点,但是#define同样具有优点,#ifndef使用。
5、Typedef int (*function)(); 解读遵循“从内到外”方法,谨记[]和()比*的结合度更紧。
6、未指定大小的extern数组是不完全类型,不能对其sizeof(),不能获取另外一个文件中数组大小。解决方法是:
File1.c : int array[] = {1,2,3}; int array_size = sizeof(array);
File2.c extern int array_size;array[];
或者是数组大小确定明确数字。
或者数组最后放置一个“哨兵”值(0、-1、NULL),这样就不需要数组大小也可以确定数组长度。Int array[] = {1,2,3,-1}:
7、C语言标志符的3个属性:作用域、命名空间和连接类型。
作用域:函数、文件、块和原型。
命名空间:行标(goto目的地)、标签(结构、枚举等名称)、结构/联合成员(每个结构、联合一个命名空间)、其他标志符(函数、变量、类型定义名称和枚举常量)。
连接类型:外部连接(全局、非静态变量和函数)、内部连接(限于文件作用域内的静态函数和变量)、无连接(局部变量和类型定义typedef 名称和枚举常量)。
8、变量初始化,静态未初始化变量确保初始化为0,自动变量(局部变量)若无显式初始化,包含垃圾内容。Malloc和realloc都包含垃圾内容。Calloc获得内存全为0.
9、Char a[]= “safsdf”,char *p = “sdafsd”;当p[i]修改时程序崩溃。转化为无名静态字符数组,只读内存,所以不能被修改。
第二章 结构、联合和枚举
1、C不是C++,不能用结构标签自动生成类型定义名。
错误做法:struct X{...}; X aa;
正确做法:struct X aa; 或者 typedef struct {....} X;X aa;
2、结构体中真正安全的做法使用字符指针,而不是数组。
例如:struct name {int len; char *name/name[MAX];};使用中,
Struct name *p = malloc(sizeof(struct name));
P->len = strlen(str); p->name = malloc(p->len+1); strncpy(p->name,str,p->len);
3、结构内容按字节写入时会出现不可移植问题,打开的时候用rb,写的时候wb。
4、结构体会自动字节对齐,为避免减少空间浪费,可以按照字节从大到小排列。为了计算元素的偏移量:
5、没有一种方法跟踪联合哪个域在使用。
6、
第三章 表达式
1、短路效应:if (p==NULL || *p == ‘\0’)
2、
3、
第四章 指针
1、char *指向int型变量,( (int* )p )++不对,转换操作符,只能生成一个右值,右值不能赋值也不能自增。
2、Void* 可以用作通用指针,因为可以和其他类型相互赋值时自动转换。但是void**不会自动转换。
第五章 空指针
1、空指针不会指向任何地方,不是任何对象或函数的地址。空指针表示“未分配”、“尚未指向任何地方”的特殊指针。
2、值为0的整形常量表达式会在编译时转为空指针。Char*p=0;unix下需要强制转为指针,(char*)0,否则不知道是指针。尤其是可变参数中需要限制转换。
3、预处理宏NULL。其值为空指针常量。0或 ( (void*) 0).
4、大端模式的PC上,0L这样特殊NULL会出问题。
5、指针上下文中NULL和0是完全等价的,使用NULL的地方在说明此处在使用指针。不能在需要ASCII空字符(NUL)的地方用NULL,#define NUL ‘\0’
6、
第六章 数组和指针
1、源文件中为char a[10],在另一个源文件中不能声明为指针,extern char* p; 必须为extern char a[];
2、数组不能对其赋值。并且数组传递时会退化为指针。
3、数组和指针的紧密联系使用指向动态分配的内存指针来模拟运行时才能确定大小的数组十分容易。
4、C99、gcc支持大小不确定的数组,但是如果不行话就是用malloc()动态申请之后free()实现。
5、分配多维数组,a[][],分配一个指针数组,每个指针动态分配”行”。
Int** p = malloc(rows * sizeof(int*));
For (i=0; i
{
P[i] = malloc( colnums * sizeof(int) );
}
6、Int array[10]; int *p = &array[-1];p当作从下表1开始。不完全符合C标准。
7、二维数组退化为数组的指针,而不是指针的指针。声明为
Void f(int a[][COLNUMS]);
Void f(int (*ap)[COLNUMS] );
若已经声明为接收指针的指针,直接传入二维数组可能毫无意义。
Extern g(int** p);
Int* ip = &array[0][0]; g(&ip); 不要使用,
8、Sizeof()返回字节大小,使用sizeof(array)/sizeof(array[0]).
第七章 内存分配。
1、函数返回指针,内容不能是局部变量,返回之后指向的内存不确定,所以数组不行,必须是malloc().
2、当生成内存时,不需要乘以sizeof(char),并且释放之后立即将他置为NULL,以明确它的状态。
3、Realloc()并不一定能在原地扩大内存区域。若不能分配足够大空间则会返回空指针,原来分配内存会保留。所以
Int *newarray = (int *)realloc( (void *)dynarray,100);
If ( newarray != NULL)
{
Dynarray = newarray;
}
4、Malloc()与calloc()之间区别就是参数、零填充。Free()同样可以释放calloc()内存。
第八章 字符和字符串
第九章 布尔表达式
第十章 C预处理器
1、多条语句的宏定义。#define MACRO(arg1,arg2) do { }while(0)
2、
3、_ _FILE_ _和_ _LINE_ _宏。#define DEBUG dbginfo( __LINE__, __FILE__)
第十一章 ANSI/ISO 标准C
1、
第十二章 标准输入输出库
1、在输出到显示器或是文件等操作时需要显示fflush(stdout)等类似调用,否则会出现没有刷新到终端或是文件的情况。
2、需要输入%,需要输入%%,转义字符,使用printf()时需要输入正确的数据类型,否则会出错。
3、Printf()会将%f输出double精度,scanf()接受的是指针,没有这种类型提升,scanf(%f)与%lf大不相同。且scanf()参数必须是指针。例如:int i,&i; char s[30], s,此时如果显示使用&,会得到错误的指针类型。注意:scanf()必须输入正确的数据类型,不能混用scanf()和gets()或是其他的输入例程的调用,scanf()对换行符的特殊处理几乎一定会带来问题,要么就用scanf()处理所有的输入,要不就不用。
4、scanf()和gets()类似,难保接收缓冲区不溢出。Scanf()适用于相对格式化、格式整齐的输入,而用户界面输入信息各种可能,可以使用fgets()读入整行,然后使用scanf()或其他方法解释内容。
5、Fscanf()与sscanf()处理字符串比较适合。
6、Sprintf()应该分配多大内存,为避免内存泄漏,缓冲区溢出,有一个方法使用fprintf()写入临时文件返回大小,之后根据大小分配。同时,可以使用限长sprintf()函数,snprintf(buf,size,”%s”,str);返回放入的字节数。
7、不要使用gets(),而使用fgets(),缓冲区溢出问题,另外,fgets()保留’\n’,很容易去掉。
8、Ftell()和fseek()用long int型表示文件内偏移量,2G以内,而fgetpos()和fsetpos()使用fpos_t类型表示偏移量,可以任意的偏移量。
9、把stdin或stdout重定向到文件:freopen(file, “w”,stdout);
10、
第十三章 库函数
1、strtok()常用方法: for (p=strtok(string,”\n”); p!=NULL; p=strtok(NULL,”\n”))
{............}
2、插入排序和归并排序用链表最合适了。
3、函数time\ctime\localtime,表示当前时间。Mktime计算日期的time_t值,使用difftime计算两time_t值之间秒数差。
4、随机数生成器:rand(),,如果需要产生一定范围内的随机整数。不要用rand()%N,而是用rand() / (Rand_MAX / N +1 );这里需要N远小于Rand_MAX 。Rand()具有可预测性,srand()具有不可预测的真正随机值生成器。是以当前时间为种子值。
5、产生正态分布或是高斯分布的随机数?P197.
第十四章 浮点型运算。
1、浮点型大小比较,不能直接==比较,而是fabs(a-b) <=**
第十五章 可变参数列表。
1、可变参数的可变部分使用默认参数提升,char和short int提升为int,float提升为double。
2、变参函数实现:
Char* fun(char* first, ...)
{
Va_list argp;
Va_start(argp, first);
While ( (p=va_arg(argp, char* ) ) != NULL )
{..........}
Va_end(argp);
}
Va_stat()与va_end()可以重复多次打开关闭。但对移植性有很大影响。
第十六章
第十七章
第十八章
第十九章
第二十章 杂项
1、使用errno之前需要将其置零,之后读取errno值判断什么类型错误。Strerror从errno得到文本。
2、Fprintf写入,fcanf读入
3、位运算