随笔分类 - C语言
摘要:在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个:1、避免goto语句:通常,如果一个函数开始要分配一些资源,然后如果在中途遇到错误则要退出函数,当然,退出前要释放资源,我们的代码可能如下: 1 #defien N 10 2 3 bool Execute() 4 { 5 // 分配资源 6 int *p = (int *)malloc(N * sizeof(int)); 7 bool bOk = true; 8 9 // 执行并进行错误处理10 bOk = func1();11 if(!...
阅读全文
posted @ 2013-10-25 13:51
cpoint
摘要:接上一篇C语言中可变参数函数实现原理,从理论上详细介绍了C语言中可变参数函数的实现,这一篇从minix内核源码中的scanf函数入手,学习C语言经典可变参数函数的实现过程在scanf.c文件中,可以看到scanf函数,代码如下:#include #include #include "loc_incl.h"int scanf(const char *format, ...){ va_list ap; int retval; va_start(ap, format); retval = _doscan(stdin, format, ap); va_e...
阅读全文
posted @ 2013-10-19 01:10
cpoint
摘要:谈到C语言中可变参数函数的实现(参见C语言中可变参数函数实现原理),有一个头文件不得不谈,那就是stdarg.h本文从minix源码中的stdarg.h头文件入手进行分析: 1 #ifndef _STDARG_H 2 #define _STDARG_H 3 4 5 #ifdef __GNUC__ 6 /* The GNU C-compiler uses its own, but similar varargs mechanism. */ 7 8 typedef char *va_list; 9 10 /* Amount of space required in an argument l...
阅读全文
posted @ 2013-10-18 00:05
cpoint
摘要:C函数调用的栈结构可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈。例如,对于函数: void fun(int a, int b, int c) { int d; ... }其栈结构为 0x1ffc-->d 0x2000-->a 0x2004-->b 0x2008-->c对于在32位系统的多数编译器,每个栈单元的大小都是sizeof(int), 而函数的每个参数都至少要占一个栈单元大小,如函数 void fun1(char a, int b, double c, ...
阅读全文
posted @ 2013-10-17 00:59
cpoint
摘要:接上一篇:C语言内存对齐详解(2)在minix的stdarg.h文件中,定义了如下一个宏:/* Amount of space required in an argument list for an arg of type TYPE. * TYPE may alternatively be an expression whose type is used. */#define __va_rounded_size(TYPE) \ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))从注释以及宏的名字可以看出是..
阅读全文
posted @ 2013-10-15 02:47
cpoint
摘要:接上一篇:C语言内存对齐详解(1) VC对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。VC 中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式;第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占
阅读全文
posted @ 2013-10-15 00:22
cpoint
摘要:一、什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在
阅读全文
posted @ 2013-10-14 21:41
cpoint
摘要:处理二维数组的函数有一处可能不太容易理解,数组的行可以在函数调用的时候传递,但是数组的列却只能被预置在函数内部。例如下面这样的定义:#define COLS 4int sum3d(int ar[][COLS], int rows){ int r, c, tot; tot = 0; for(r = 0; r 2 3 #define ROWS 3 4 #define COLS 4 5 6 int sum2d(int rows, int cols, int ar[rows][cols]) 7 { 8 int i, j, sum; 9 sum = 0;10 11...
阅读全文
posted @ 2013-10-14 14:42
cpoint
摘要:编写函数expand(s1,s2), 将字符串s1中类似于a-z一类的速记符号在字符串s2中扩展为等价的完整列表abc……xyz。该函数可以处理大小写字母和数字,并可以处理a-b-c、a-z0-9与a-z等类似的情况。作为前导和尾随的字符原样复制 1 #include 2 #include 3 #include 4 5 int judge(char a, char b) //判断'-'两端的字符是否符合速记符号扩展的要求 6 { 7 if(isdigit(a) && isdigit(b)) 8 { 9 if(a < b) return 1;10 ...
阅读全文
posted @ 2013-10-14 01:54
cpoint
摘要:编写函数itob(n,s,b),将整数n转换为以b为底的数,并将转换结果以字符的形式保存到字符串s中。e.g.itob(n,s,16)把整数n格式化为十六进制整数保存在s中。 1 #include 2 #include 3 #include 4 5 void swap(char *a, char *b) 6 { 7 int t; 8 t = *a; 9 *a = *b;10 *b = t;11 }12 13 void reverse(char *s) //倒置串s14 {15 int c, i, j;16 i = 0;17 j = s...
阅读全文
posted @ 2013-10-14 01:53
cpoint
摘要:统计行数、单词数,字符数的程序: 1 #include 2 3 #define IN 1 /*在单词内*/ 4 #define OUT 0 /*在单词外*/ 5 6 int main() 7 { 8 int c, nl, nw, nc, state; 9 10 state = OUT;11 nl = nw = nc = 0; //nl:行数 nw:单词数 nc:字符数12 while((c = getchar()) != EOF) {13 ++nc;14 if(c == '\n')15 ...
阅读全文
posted @ 2013-10-14 01:35
cpoint
摘要:在看minix中bsearch实现的源代码之前,先学习一下C 语言中void类型以及void*类型的使用方法与技巧。void的含义:void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据。void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义:void a;这行语句编译时会出错,提示“illegal use of type 'void'”。即使void a的编译不会出错,它也没有任何实际意义。 众所周知,如果指针p1和p2的类型相同,那么我们可以直接在p1和p2间互相赋值;如果p1和p2指向不
阅读全文
posted @ 2013-10-14 00:56
cpoint
摘要:assert宏的原型定义在中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:#include void assert( int expression );assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。请看下面的程序清单badptr.c: 1 #include 2 #include 3 #include 4 int main( void ) 5 { 6 FILE *fp; 7 8 fp = fopen( "test.txt",...
阅读全文
posted @ 2013-10-04 23:58
cpoint
摘要:1、炮弹一样的球状物体,能够堆积成一个金字塔,在顶端有一个炮弹,它坐落在一个4个炮弹组成的层面上,而这4个炮弹又坐落在一个9个炮弹组成的层面上,以此类推。写一个递归函数CannonBall,这个函数把金字塔的高度作为参数,并且返回它所包括的炮弹数量。函数必须按照递归方式实现,不可以使用迭代结构,例如while或for。 1 int CannonBall(int h) 2 { 3 if(h == 1) return 1; 4 else 5 return CannonBall(h-1) + pow(h,2); 6 } 7 8 int main(void) 9 {1...
阅读全文
posted @ 2013-10-02 16:44
cpoint
摘要:将十进制数转换为二进制数:非递归算法: 1 void translate(int n) //将10进制转换为8位的二进制 2 { 3 int a[10]; 4 int i,j; 5 i=0; 6 while(1) 7 { 8 a[i++]=n%2; 9 if(n/2==0) break; 10 n/=2; 11 } 12 i--; 13 for(j=1; j=0; j--) 18 { 19 printf("%d",...
阅读全文
posted @ 2013-10-01 17:46
cpoint
摘要:内存区域可以分为栈、堆、静态存储区和常量存储区,局部变量,函数形参,临时变量都是在栈上获得内存的,它们获取的方式都是由编译器自动执行的。利用指针,我们可以像汇编语言一样处理内存地址,C 标准函数库提供了许多函数来实现对堆上内存管理,其中包括:malloc函数,free函数,calloc函数和realloc函数。使用这些函数需要包含头文件stdlib.h。 四个函数之间的有区别,也有联系,我们应该学会把握这种关系,从而编出精炼而高效的程序。在说明它们具体含义之前,先简单从字面上加以认识,前3个函数有个共同的特点,就是都带有字符”alloc”,就是”allocate”,”分配”的意思,也就是给..
阅读全文
posted @ 2013-09-25 20:32
cpoint
摘要:1.基本函数在C语言中取随机数所需要的函数是:int rand(void);void srand(unsigned int n);rand()函数和srand()函数被声明在头文件stdlib.h中,所以要使用这两个函数必须包含该头文件: #include2.使用方法 rand()函数返回0到RAND_MAX之间的伪随机数(pseudorandom)。RAND_MAX常量被定义在stdlib.h头文件中。其值等于32767,或者更大。 srand()函数使用自变量n作为种子,用来初始化随机数产生器。只要把相同的种子传入srand(),然后调用rand()时,就会产生相同的随机数序列。因此,我.
阅读全文
posted @ 2013-08-02 17:22
cpoint
摘要:带参数的宏定义有如下的格式:【#define 指令----带参数的宏】 #define 标识符(x1,x2,……,xn)其中 x1,x2,……xn是标志符(宏的参数)注意:在宏的名字和括号之间必修没有空格。如果有空格,预处理会认为是在定义一个简单的宏,其中(x1,x2,……,xn)是替换列表的一部分当预处理器遇到一个带参数的宏,会将定义存储起来以便以后使用。在后面的程序中,如果任何地方出现了标识符(y1,y2……,yn)格式的宏调用(其中y1,y2, ……yn是一些列标记),预处理器会使用替换列表替代,并使用yi替换xie.g. 假如我们定义了如下的宏:#define MAX(x,y) ((.
阅读全文
posted @ 2013-07-11 23:09
cpoint
摘要:C程序的源代码中可包括各种编译指令,这些指令称为预处理命令。虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境。本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性。ANSI标准定义的C语言预处理程序包括下列命令:#define,#error,#include,#if,#else,#elif,#endif,#ifdef,#ifndef,#undef,#line,#pragma等。非常明显,所有预处理命令均以符号#开头,下面分别加以介绍。一 #define命令#define定义了一个标识符及一个串。在源程序中每次遇到该标识符时,均以定义的串代换它。ANSI标准将标识符
阅读全文
posted @ 2013-04-07 02:18
cpoint
摘要:C 中常用到的宏有:01: 防止一个头文件被重复包含#ifndef COMDEF_H#define COMDEF_H//头文件内容#endif02: 重新定义一些类型防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。typedef unsigned char boolean; /* Boolean value type. */typedef unsigned long int uint32; /* Unsigned 32 bit value */typedef unsigned short uint16; /* Unsigned 16 bit value */typedef u
阅读全文
posted @ 2013-04-05 23:03
cpoint

浙公网安备 33010602011771号