C语言笔试题答案
一、 简答题
1. 程序的局部变量存在于(栈)中,全局变量存在于(静态区)中,动态申请数据存在于
(堆)中。 2. 设有以下说明和定义:
typedef union {long i; int k[5]; char c;} DATE; struct data { int cat; DATE cow; double dog;} too; DATE max;
则语句 printf(\的执行结果是:_______
data是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20。
data是一个struct, 每个变量分开占用空间. 依次为int4 + DATE20 + double8 = 32.所以结果是 20 + 32 = 52。
3. 32位系统下,请问如下语句的值
unsigned char *p1; unsigned long *p2;
p1=(unsigned char *)0x801000; p2=(unsigned long *)0x810000; 请问p1+5=0x801005 p2+5=0x810014
4. int i=10, j=10, k=3; k*=i+j; k最后的值是?
答:60,此题考察优先级,实际写成: k*=(i+j);,赋值运算符优先级最低 5. #define DOUBLE(x) x+x ,i = 5*DOUBLE(5); i 是多少?
答案:i 为30。
6. 下面程序的输出是_____,为什么? char *ptr;
if ((ptr = (char *)malloc(0)) == NULL) {
puts(\} else {
puts(\}
答:Got a valid pointe
7. 以下程序运行后的输出结果是______ 。
main()
{
char m;
m='B'+32; printf(\}
答:b
8. 已有定义如下:
struct node {
int data;
struct node *next; } *p;
以下语句调用malloc函数,使指针p指向一个具有struct node类型的动态存储空间。请填空p = (struct node *)malloc(________); 答:sizeof(struct node)
9. 在绝对地址0xXXXXXXXX上写入字符’a’的语句是___________。
答:unsigned char *p = (unsigned char *)0xF000FF00; *p = ‘a’;
10. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)。 #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
1)#define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
2)懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。 3) 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
4)如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。
11. 写一个\标准\宏MIN ,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A) <= (B) ? (A) : (B))
1)标识#define在宏中应用的基本知识。这是很重要的。因为在嵌入(inline)操作符 变为标准C的一部分之前,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
2)三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
3)懂得在宏中小心地把参数用括号括起来,因为#define仅仅做替换,如果我们写 #define MUL(a,b) a/b 的话,那么我写MUL(a+1,b-1)替换之后的表达式就为a+1/b-1,这个结果显然是违背我们定义的目的的。
12. 嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢? 这个问题用几个解决方案。 while(1){}或者for(;;){} 13. 用变量a给出下面的定义
a) 一个整型数(An integer)
b) 一个指向整型数的指针( A pointer to an integer) c) 一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to
an intege)
d) 一个有10个整型数的数组( An array of 10 integers) e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to
integers)
f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers)
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a
function that takes an integer as an argument and returns an integer)
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一
个整型数( An array of ten pointers to functions that take an integer argument and return an integer ) 答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
14. 关键字static的作用是什么?
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。
static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件。
static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;
static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;
static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。 15. 关键字const的含义。
声明一个只读变量,可用于修饰指针,变量,形参等等 const int a;修饰变量 int const a;修饰变量
const int *a;修饰指针的指向,表示不希望通过指针改变指向的这个空间的值
int * const a;修饰指针变量,表示不希望改变指针变量p的值,也就是指针的指向
const int const * a ;表示不希望通过指针改变指针指向的这个空间存储的值也不希望改变指针的指向。
16. 关键字volatile有什么含意?并给出三个不同的例子。
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1) 并行设备的硬件寄存器(如:状态寄存器)
2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 3)多线程应用中被几个任务共享的变量
17. 一个参数既可以是const还可以是volatile吗?解释为什么。
是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。 18. 一个指针可以是volatile 吗?解释为什么。
是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
19. 下面的函数有什么错误:
int square(volatile int *ptr) {
return *ptr * *ptr; }
这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码: int square(volatile int *ptr) {
int a,b; a = *ptr; b = *ptr; return a * b; }
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下: long square(volatile int *ptr) {
int a; a = *ptr; return a * a;
}
20. 在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个
纯粹的ANSI编译器。写代码去完成这一任务。
答:
int *ptr;
ptr = (int *)0x67a9; *ptr = 0xaa55;
21. 局部变量能否和全局变量重名?
答:能,局部会屏蔽全局。要用全局变量,需要使用\。局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。 22. 如何引用一个已经定义过的全局变量?
答:extern
可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错。
23. 全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?
答:可以,在不同的C文件中以static形式来声明同名全局变量。可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错。
24. 语句for( ;1 ;)有什么问题?它是什么意思? 答:和while(1)相同,死循环。
25. do……while和while……do有什么区别?
答:前一个循环一遍再判断,后一个判断以后再循环。 26. 下列哪种方法更好,为什么?
define dPS struct s * typedef struct s * tPS;
以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?
这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子: dPS p1,p2; tPS p3,p4; 第一个扩展为 struct s * p1, p2;
上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。 27. 下面的结构是合法的吗,如果是它做些什么?
int a = 5, b = 7, c; c = a+++b;
根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:
c = a++ + b;
因此, 这段代码持行后a = 6, b = 7, c = 12。 28. 队列和栈有什么区别?
队列先进先出,栈后进先出
29. 全局变量和局部变量是否有区别?如果有,是什么区别? 全局变量储存在静态数据库,局部变量在堆栈。 全局变量的作用域在定义之下的任何位置 而局部变量的作用域在函数模块内
全局变量的生命周期从编译开始到程序结束 而局部变量的声明周期从定义开始到函数结束 30. 堆栈溢出一般是由什么原因导致的? 没有回收垃圾资源。
31. 冒泡排序算法的时间复杂度是什么?
时间复杂度是O(n^2)。
32. 分别写出BOOL,int,float,指针类型的变量a 与“零”的比较语句。
答案:
BOOL : if ( !a ) or if(a) int : if ( a == 0)
float : const EXPRESSION EXP = 0.000001 if ( a < EXP && a >-EXP)
pointer : if ( a != NULL) or if(a == NULL) 33. 不能做switch()的参数类型是: switch的参数不能为实型。
34. 某32位系统下,请计算sizeof 的值.
char str[] = “http://www.ibegroup.com/” char *p = str ; int n = 10;
请计算
sizeof (str ) = ? (1) sizeof ( p ) = ? (2) sizeof ( n ) = ? (3) void Foo ( char str[100]){ sizeof( str ) = ? (4) }
void *p = malloc( 100 ); sizeof ( p ) = ? (5) 答:(1)字符串末尾有 ‘\\0’字符,所以是17
(2)4 (3)4
(4)str是指针而并非数组,所以是4 ,在形参中不能定义数组,所有以数组形式出现的都是指针
(5)p的类型是指针所以是4
35. 请说出const与#define 相比,有何优点?
答:
1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
2) 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。 36. 回答下面的问题.
a) 头文件中的 ifndef/define/endif 干什么用?预处理 答:防止头文件被重复引用
b) #include
答:前者用来包含开发环境提供的库头文件,后者用来包含自己编写的头文件。 37. 使用malloc()函数时,为什么要将其返回值强制转换成被赋值指针变量的数据类型? 答:因为malloc返回值为void *型指针,对于void*型指针必须先强制类型转换才能够使用。
38. 列举一个软件中时间换空间或者空间换时间的例子。
答:
void swap(int a,int b) {
int c; c=a;a=b;b=a; } 空间换时间
void swap(int a,int b) {
a=a+b;b=a-b;a=a-b; } 39. 以下C语言语句有什么区别
char * const p; char const * p; const char *p; 答:
char * const p; //常量指针,p的值不可以修改
char const * p;//指向常量的指针,指向的常量值不可以改 const char *p; //和char const *p
40. 下面x, y, *p的值是多少,有什么问题?
int x, y, z = 2; int *p=&z;
x=sizeof*p; y=x/*p;
答:如果你按这个写出来,肯定编译不过去。最明显的:y=x/*p;应该改为y=x/(*p) 还有sizeof*p改为sizeof(*p); y = 2 ,x = 4, z = 2,*p = 2;
41. 下面的语句是什么意思?如何声明或定义才使它们更易懂?(10分)
int (*foo())(); int (*foo())[]; int (*foo[])(); (*(void(*)())0)();
void (*signal(int,void(*)(int)))(int);
答:
第一个:int (*foo())();
先一步一步的分析:首先是被左边的()括起来的*foo()。 (1) 里面()的优先级高于*,所以foo()先是一个函数; (2) *foo()说明这个函数返回一个指针;
(3) (*foo())()这个函数返回的指针指向一个函数; (4) int (*foo())();
(5) 最后这个函数返回一个整型数。 第二个:int (*foo())[]; 有上面的打基础了,这回好多了。大致还是那个意思,但是就是由函数变成了数组,所以还更简单些,具体的含义是:foo()函数返回的指针指向一个具有整型数的数组。 第三个:int (*foo[])();
这个就是上两个的翻版:一个存有指针的数组*foo[],该指针指向一个函数,该函数返回一个整型数。 第四个:(*(void(*)())0)();
(1) 最里面的(*)()意思是一个指向函数的指针;
(2) 加个前缀void(*)(),表示一个指向返回类型为void的函数的指针; (3) 套个马甲(void(*)())的意思就是类型强制转换;
(4) (void(*)())0就是把0强制转换成前面说的那个类型的指针;
(5) 那么好,现在(void(*)())0是一个指针了,这个指针指向了一个函数,我们用宏定义简化一下,看着太麻烦:
(6) #define ptr (void (*)())0 ,现在(*(void(*)())0)();这个怪物就可以简化成:(*ptr)(); (7) 别忘了ptr是一个指向函数的指针,既然这样*ptr就是函数了,那么上面的结果再次被简化成:ptr();,这不就是函数的调用么!
至此这个怪物函数的含义和简化形式就都给出了,我就不再总结了。不过我还想再给出一个简化形式,这会对下面的问题有启示:
使用typedef,typedef void (*ptr)(); ,然后就可以用(*(ptr)0)();来表示这个怪物函数了,其灵活性比使用#define要高。
第五个:void (*signal(int,void(*)(int)))(int);
这是著名的signal函数的原型,可以如此声明: typedef void (*HANDLER)(int); HANDLER signal(int,HANDLER); 或者:
typedef void HANDLER(int);
HANDLER *signal(int,HANDLER *);
42. 如何定义Bool变量的TRUE和FALSE的值。
答:#define TURE 1 #define FALSE 0
43. 运行char a*+ = ”abc”后,内存会开辟几块内存,这此内存共占多少个字节?
答:这句话为定义数组,省略下表后根据元素个数决定,因为“abc”为字符串,加上末尾‘\\0’共有4个元素所以是四个字节。
44. 运行char *p = ”abc”后,内存会开辟几块内存,这此内存共占多少个字节?
答:这句话为定义指针指向字符串常量区字符串“abc”,任何指针都为4个字节,所以共占4个字节。
45. 说出 int *(*p)[3]; p是什么变量?如果p是指针变量,那么p+1的偏移量是多少? 答:p为指针变量,p指向类型为装了三个元素的指针数组,因为所有指针在32位系统下都是四个字节,所以偏移量为12个字节。 46. 一个32位的机器,该机器的指针是多少位?
答:32位
47. 已知一个数组table,用一个宏定义,求出数据的元素个数
答:#define length(table) (sizeof(table)/sizeof(table[0]))
二、 程序分析题
1. 下面的代码有什么问题?
char *_strdup( const char *strSource ) {
static char str[MAX_STR_LEN]; strcpy(str, strSource); return str; }
答:返回局部变量地址。
2. 下面的代码输出是什么,为什么?
void foo(void) {
unsigned int a = 6; int b = -20;
(a+b > 6) ? puts(\} 答:这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 \。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。
3. 请写出下列代码的输出内容
#include main() {
int a,b,c,d; a=10; b=a++; c=++a; d=10*a++;
printf(\,c,d:%d,%d,%d\,b,c,d); return 0; }
答:10,12,120
4. Test函数的运行结果如何?
void GetMemory(char *p) {
p = (char *)malloc(100); }
void Test(void) {
char *str = NULL; GetMemory(str);
strcpy(str, \printf(str); }
答:段错误,GetMemory(str)传的是str地址并没有改变str的值,所以p并不能够改变str的指向,str依然是NULL,strcpy向NULL赋值造成段错误。 5. Test函数的运行结果如何?
char *GetMemory(void) {
char p[] = \return p; }
void Test(void) {
char *str = NULL; str = GetMemory(); printf(str); }
答:返回局部变量地址。 6. Test函数的运行结果如何?
Void GetMemory2(char **p, int num) {
*p = (char *)malloc(num);
}
void Test(void) {
char *str = NULL;
GetMemory(&str, 100); strcpy(str, \printf(str); }
答:内存溢出,malloc申请的空间使用结束之后没有释放 7. Test函数的运行结果如何?
void Test(void) {
char *str = (char *) malloc(100); strcpy(str, “hello”); free(str);
if(str != NULL) {
strcpy(str, “world”); printf(str); } }
答:一内存溢出,二free释放malloc申请的内存空间之后继续操作该空间,但是该程序能够打印出world 但是操作是非法的。 8. 写出下列代码的输出内容
#include int inc(int a) {
return(++a); }
int multi(int*a,int*b,int*c) {
return(*c=*a**b); }
typedef int(FUNC1)(int in);
typedef int(FUNC2) (int*,int*,int*);
void show(FUNC2 fun,int arg1, int*arg2) {
INCp=&inc;
int temp =p(arg1);
fun(&temp,&arg1, arg2); printf(\}
main() {
int a;
show(multi,10,&a); return 0; }
答:110
9. 请找出下面代码中的所以错误
说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba” #include\main() {
char*src=\char* dest=NULL; int len=strlen(src);
dest=(char*)malloc(len); char* d=dest; char* s=src[len]; while(len--!=0) d++=s--;
printf(\return 0; } 答: 方法1:
int main() {
char* src = \ int len = strlen(src);
char* dest = (char*)malloc(len+1);//要为0分配一个空间 char* d = dest;
char* s = &src[len-1];//指向最后一个字符 while( len-- != 0 ) *d++=*s--;
*d = 0;//尾部要加0 printf(\
free(dest);// 使用完,应当释放空间,以免造成内存汇泄露 return 0; }
方法2:
Int main() {
char str[]=\ int len=strlen(str); char t;
}
for(int i=0; i { t=str[i];
str[i]=str[len-i-1]; str[len-i-1]=t; }
printf(\return 0;
10. 以下程序有什么错误
试题1: void test1() {
char string[10];
char* str1 = \strcpy( string, str1 ); }
答:数组越界string数组只有十个元素空间,字符串str1有11个字节 试题2: void test2() {
char string[10], str1[10]; int i;
for(i=0; i<10; i++) {
str1 = 'a'; }
strcpy( string, str1 );
}
答:有可能造成数组越界,str1里所有元素都是字符‘a’,strcpy复制遇到‘\\0’才会停止,而str1数组里没有字符串结束标志‘\\0’,所以有可能造成数组越界。 试题3:
void test3(char* str1) {
char string[10];
if( strlen( str1 ) <= 10 ) {
strcpy( string, str1 ); } }
答:if(strlen(str1) <= 10)应改为if(strlen(str1) < 10),因为strlen的结果未统计’\\0’所占用的1个字节。
11. 下面程序的运行结果:
main() {
int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1);
printf(\}
答: 2,5
12. 请问以下代码有什么问题:
int main() {
char a; char *str=&a; strcpy(str,\ printf(str); return 0; }
答:没有为str分配内存空间,将会发生异常问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。 13. 交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3;
答:
a = a ^ b; b= a ^ b; a = a ^ b; 14. 以下是求一个数的平方的程序,请找出错误:
#define SQUARE(a) ((a)*(a)) int a=5; int b;
b=SQUARE(a++);
答:要写成int a=5; a++; b=SQUARE(a),不然直接传a++的值还是5。 15. 下面的程序运行结果是( )
设int arr[]={6,7,8,9,10}; int *ptr=arr; (ptr++)+=123;
printf("%d,%d",*ptr,*(++ptr)); 答:8,8
16. 下面的两段代吗?有什么区别?什么时候需要使用代码2?
1、
int i = 10; int j = i; int k = i; 2、
volatile int i = 10; int j = i; int k = i;
答:代码1,这时候编译器对代码进行优化,因为在代码1中的两条语句之间i没有被用作左值(即没有被赋值),这时候编译器认为i的值没有发生改变,所以在第1条语句时从内存取出i的值赋给j之后,这个值并没有被丢掉,而在第2条语句时,继续用
这个值给k赋值。编译器不会生成汇编代码重新从内存读取i的值。 代码 2 ,volatile 关键字告诉编译器,i是随时可能发生的变化的,每次使用它的时候,必须从内存中取出i的值。因而编译器生成的汇编代码会重新从i的地址处读取数据放在k中。
代码2 ,的使用时机,如果i是一个寄存器变量,表示一个商品数据或者是多个线程的共享数据,那么就容易出错,所以说volatile可以保证对特殊地址的稳定访问。 17. printf(\输出?
答:7。
18. 在32位的X86系统下,输出的值为多少?
#include
int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&a + 1); int *ptr2 = (int *)((int)a + 1); printf(\
//注意从高字节开始打印 return 0;
} 答:5,2
19. 下面代码的有问题吗?为什么?
#include
char c = a[3]; }
int main() {
char b[10] = \func(b[10]); return 0; }
答:这里至少有两上严重错误,
第一,b[10]并不存在,在编译的时候,由于没有去实际地址取值,所以没有出错。但在运行的时,
将计算b[10]的实际地址,并且取值。这时候发生越界错误。
第二,func函数会将传入的char类型的数据当作地址处理,同样会发生错误 。 20. 下面代码输出的结果是多少?
#include
if(i>0) {
fun(i/2);
}
printf(\}
int main() {
fun(10); return 0; }
答:0,1,2,5,10 析:递归展开
三、 编程题
1. 不调用库函数,自己实现memcpy函数。
typedef int size_tt;
void *memcpy(void *dest,const void *src,size_tt count)//源串要有const修饰 {
char *pDest=(char*)(dest);//将原始指针赋给新变量 const char *pSrc=(const char*)(src); //判断传参是否合法 if(NULL == dest || NULL == src) { return NULL; }
//目的地址和源地址重叠,从源地址的末尾方向开始拷贝 if( pDest > pSrc && pDest < pSrc+count) {
//将指针指向末尾
pDest = pDest + count-1; pSrc = pSrc + count-1; while(count--) {
*pDest--=*pSrc--; } }
//目的地址和源地址不重叠,从源地址的开始方向拷贝 else {
while(count--) {
*pDest++=*pSrc++; }
}
return pDest;//返回,这样可以嵌套使用 }
2. 不调用库函数,自己实现strcpy函数 。
int Strcmp(const char *str1, const char *str2) { assert(str1 && srt2); while(*str1 && *str2 && (*str1 == *str2)) {
str1++; str2++; }
return (*str1 - *str2); }
3.
a) 编写strcat函数,已知strcat函数的原型是char *strcat (char *strDest, const char
*strSrc);其中strDest 是目的字符串,strSrc 是源字符串(不能调用库函数)。
#include
char *strcat (char * dst, const char * src) { if(NULL == dst || NULL == src) { return NULL; } char * cp = dst; while( *cp ) cp++; /* find end of dst */ while( *cp++ = *src++ ) ; /* Copy src to end of dst */ return dst; /* return dst */ }
int main() { char str1[100] = \ char str2[] = \ printf(\ return 0; }
b) strcat能把strSrc 的内容连接到strDest,为什么还要char * 类型的返回值?
答:方便赋值给其他变量
4. 两个字符串,s,t;把t字符串插入到s字符串中,s字符串有足够的空间存放t字符串。
char *insert(char *t, const char *s) { char *q = t; const char *p =s; if(NULL == q) return NULL; while(*p != '\\0') { p++; } while(*q != 0) { *p = *q; p++; q++; } *p = '\\0'; return t; } 5. 写一函数,实现删除字符串str1中含有的字符串str2。
#include
char *delstr(char *src,const char *sub) { char *st = src,*s1 = NULL; const char *s2 = NULL; while (*st && *sub) { s1 = st; s2 = sub; while (*s1 && *s2 && !(*s1 - *s2) ) { s1++; s2++; } if (!*s2) { while (*st++ = *s1++); st = src; } st++;
} return (src); }
int main() { char str1[] = \ char str2[] = \ printf(\ return 0; }
6. 编程,判断存储方式是大端存储,还是小端存储,并说出为什么要进行大小端的判定?
int check_little_endian() { union{ int a; char b; }c; c.a=1; return (c.b == 1); }
int check_little_endian() { int i = 0x00000001; char *p = &a; return *P; }
static union {
charc[4];
unsigned long l; }endian_test = {{'l','?','?','b'}};
#define ENDIANNESS((char)endian_test.l)
7. 不调用库函数,自己实现long atol(const char *nptr)函数。
long __cdecl atol( const char *nptr ) /*1.const修饰*/ { int c; /* current char */ long total; /* current total */
int sign; /* if ''-'', then negative, otherwise positive */ /* skip whitespace */
/*char ,signed char 、unsigned char 类型的数据具有相同的特性然而当你把一个单字节的数赋给一个整型数时,便会看到它们在符号扩展上的差异。*/
/*ascii码当赋给整形数时要转为unsigned char再转为int */ while ( isspace((int)(unsigned char)*nptr) ) /*2.去掉首部的空格*/ ++nptr;
c = (int)(unsigned char)*nptr++; /*取得第一个非空格的字符*/ sign = c; /* save sign indication */
if (c == '-' || c == '+') /*如果第一个非空格字符为符号*/ c = (int)(unsigned char)*nptr++; /* skip sign */ /*跳过符号,将符号后的那个字符给c*/
total = 0; /*结果置为0*/ while (isdigit(c)) { /*3.如果碰到非法字符则停止*/ total = 10 * total + (c - '0'); /* accumulate digit */ c = (int)(unsigned char)*nptr++; /* get next char */ } if (sign == '-') return -total; else return total; /* return result, negated if necessary */ }
8. 编写strcat函数()。已知strcat函数的原型是char *strcat (char *strDest, const char *strSrc);
其中strDest 是目的字符串,strSrc 是源字符串。
a) 不调用C++/C 的字符串库函数,请编写函数 strcat。
char * __cdecl strcat (char * dst, const char * src) { insert(dest != NULL && src != NULL); char * cp = dst; while( *cp ) cp++; /* find end of dst */ while( *cp++ = *src++ ) ; /* Copy src to end of dst */ return( dst ); /* return dst */ }
b) strcat能把strSrc 的内容连接到strDest,为什么还要char * 类型的返回值?
答:方便赋值给其他变量
③int NumberOf1_Solution3(int i) {
int count = 0;
while (i) {
++ count; i = (i - 1) & i; }
return count; }
29. 费波那其数列,1,1,2,3,5??编写程序求第十项。可以用递归,也可以用其他方
法,但要说明你选择的理由。
int main() { printf(\ printf(\ return 0; }
/* 递归算法 */ int Pheponatch(int N) { if( N == 1 || N == 2) { return 1; } else return Pheponatch( N -1 ) + Pheponatch( N -2 ); }
/* 非递归算法 */ int Pheponatch2(int N) { int x = 1, y = 1, temp; int i = 2; while(1) { temp = y; y = x + y; x = temp; i++;
}
if( i == N ) break; } return y;
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库C语言笔试题答案在线全文阅读。
相关推荐: