C语言面试题

1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 




2. 写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A) <= (B) (A) : (B)) 
注意大小写的问题、括号的问题
4. 嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
这个问题用几个解决方案。我首选的方案是: 
while(1) 


一些程序员更喜欢如下方案: 
for(;;) 


第三个方案是用 goto 
Loop: 
... 
goto Loop;


5. 用变量a给出下面的定义 
a) 一个整型数(An integer)  int a
b) 一个指向整型数的指针(A pointer to an integer) int* ptr
c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer) int** ptr
d) 一个有10个整型数的数组(An array of 10 integers) int a[10]
e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)int* p[10] 
f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers) in (*p)[10]
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer) int (*p)(int)
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )int (*p[10])(int)


答案是: 
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 


6. 关键字static的作用是什么?
这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用: 
1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 
2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。 
3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。 


修饰变量:在函数内,表示此变量在调用的过程中它的值维持不变;
          在函数外,表示静态变量,可以被本文件使用,但不能被其他文件使用。
修饰函数:表示是静态函数,只能被该文件中其他函数调用;


7.关键字const是什么含意? 
const int a; 表示a是一个常整数
int const a; 表示a是一个常整数
const int *a; 表示a是一个指向常整数的指针
int * const a; 表示a是一个指向整数类型的常指针
int const * a const;表示a是一个指向常整数类型的常指针


前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。


8. 关键字volatile有什么含意 并给出三个不同的例子。
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 
1). 并行设备的硬件寄存器(如:状态寄存器) 
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 
3). 多线程应用中被几个任务共享的变量 


表示该变量是易变的,编译器不应该去优化该值,即编译器不会去假设这个变量的值。它必须去内存中重新获取该值,而不是用寄存器中保存的值。
(1)并行设备的硬件寄存器
(2)一个服务子程序中访问到的非自动变量。
(3)多线程应用中被几个任务共享的变量。




1). 一个参数既可以是const还可以是volatile吗?解释为什么。 
可以,比如寄存器变量,我们希望它是只读的,但是仍可能是易变的。
2). 一个指针可以是volatile 吗?解释为什么。 
buffer指向一个地址被A线程使用,B线程修改了buffer所指的地址,同时希望A线程使用新地址,设置volatile。
3). 下面的函数有什么错误: 
int square(volatile int *ptr) 

return *ptr * *ptr; 

Ptr由于是volatile类型,是易变的,两次取得的值可能不一样。因此此函数可能无法完成平方的功能。
Ptr内容可能被修改,无法保证两次取得同一个值,应该先取出值放入一个变量中,然后通过这个变量来计算
9. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。
#define BIT3 (0x1<<3) 
static int a; 
void set_bit3(void) 

a |= BIT3; 

void clear_bit3(void) 

a &= ~BIT3; 



#define BIT3 (0x1<<3) //注意括号
void set_bit3(void)

  a | =BIT3
}
Void clear_bit3
{
  A&=~BIT3
}


10. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。
Int *p;
P=(int*)0x67a9;
*p=0xaa66;


Int *p=(int *)0x67a9;
*p=0xaa6;




11. 中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字__interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。
__interrupt double compute_area (double radius) 

double area = PI * radius * radius; 
printf(" Area = %f", area); 
return area; 
}
(1)中断不应该有返回值
(2)中断子程序中应该尽量少使用浮点类型,因为不可重入,以及printf也是不可重入的,在不同平台移植会出错。
(3)中断不应该传参


12 . 下面的代码输出是什么,为什么?
void foo(void) 

unsigned int a = 6; 
int b = -20; 
(a+b > 6) puts("> 6") : puts("<= 6"); 
}
>6  
无符号整形和符号整形数字相加时,后者自动转化为无符号整形,因此应该是>6
13. 评价下面的代码片断:


unsigned int zero = 0; 
unsigned int compzero = 0xFFFF; 
/*1's complement of zero */
因为不知道该平台是几位的,因此这个写法是不对的,正确写法应该是
unsigned int compzero=~0;


14. 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?
主要有三种类型:
内存泄露、
内存碎片、
内存崩溃  
内存崩溃是内存使用最严重的结果,主要原因有数组访问越界、写已经释放的内存、指针计算错误、访问堆栈地址越界等等。碎片收集的问题,变量的持行时间等等
下面的代码片段的输出是什么,为什么?


char *ptr; 
if ((ptr = (char *)malloc(0)) == NULL) 
puts("Got a null pointer"); 
else 
puts("Got a valid pointer"); 
该代码的输出是“Got a valid pointer”。




15. Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子: 
#define dPS struct s * 
typedef struct s * tPS; 


答案是:typedef更好。思考下面的例子: 
dPS p1,p2; 
tPS p3,p4;
第一个扩展为 
struct s * p1, p2;


上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。


16. C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么? 
int a = 5, b = 7, c; 
c = a+++b;
上面的代码被处理成: 
c = a++ + b; 
因此, 这段代码持行后a = 6, b = 7, c = 12。 


17.找错题


  试题1:


void test1()
{
 char string[10];
 char* str1 = "0123456789";
 strcpy( string, str1 );



  试题2:
















void test2()
{
 char string[10], str1[10];
 int i;
 for(i=0; i<10; i++)
 {
  str1[i] = 'a';
 }
 strcpy( string, str1 );



  试题3:


void test3(char* str1)
{
 char string[10];
 if( strlen( str1 ) <= 10 )
 {//假如str1=10,那么它的长度就是11了,拷贝不下了
  strcpy( string, str1 );
 }



  解答:


  试题1字符串str1需要11个字节才能存放下(包括末尾的’\0’),而string只有10个字节的空间,strcpy会导致数组越界;


  对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;


  对试题3,if(strlen(str1) <= 10)应改为if(strlen(str1) < 10),因为strlen的结果未统计’\0’所占用的1个字节。


18.写出字符串strcpy的函数实现过程式
void strcpy( char *strdest, char *strsrc )
{
  while( (*strdest++ = * strsrc++) != ‘\0’ );



  4分


void strcpy( char *strdest, const char *strsrc ) 
//将源字符串加const,表明其为输入参数,加2分
{
  while( (*strdest++ = * strsrc++) != ‘\0’ );



  7分


void strcpy(char *strdest, const char *strsrc) 
{
 //对源地址和目的地址加非0断言,加3分
 assert( (strdest != null) && (strsrc != null) );
 while( (*strdest++ = * strsrc++) != ‘\0’ );

  10分


//为了实现链式操作,将目的地址返回,加3分!


char * strcpy( char *strdest, const char *strsrc ) 
{
 assert( (strdest != null) && (strsrc != null) );
 char *address = strdest; 
 while( (*strdest++ = * strsrc++) != ‘\0’ ); 
  return address;







 


 20.经典getmemory问题讨论
试题4:


void getmemory( char *p )
{
 p = (char *) malloc( 100 );
}


void test( void ) 
{
 char *str = null;
 getmemory( str ); 
 strcpy( str, "hello world" );
 printf( str );



  试题5:


char *getmemory( void )

 char p[] = "hello world"; 
 return p; 
}


void test( void )

 char *str = null; 
 str = getmemory(); 
 printf( str ); 



  试题6:


void getmemory( char **p, int num )
{
 *p = (char *) malloc( num );
}


void test( void )
{
 char *str = null;
 getmemory( &str, 100 );
 strcpy( str, "hello" ); 
 printf( str ); 



  试题7:


void test( void )
{
 char *str = (char *) malloc( 100 );
 strcpy( str, "hello" );
 free( str ); 
 ... //省略的其它语句



  解答:


  试题4传入中getmemory( char *p )函数的形参为字符串指针,在函数内部修改形参并不能真正的改变传入形参的值,执行完


char *str = null;
getmemory( str ); 


  后的str仍然为null;


  试题5中


char p[] = "hello world"; 
return p; 


  的p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放。这是许多程序员常犯的错误,其根源在于不理解变量的生存期。


  试题6的getmemory避免了试题4的问题,传入getmemory的参数为字符串指针的指针,但是在getmemory中执行申请内存及赋值语句


*p = (char *) malloc( num ); 


  后未判断内存是否申请成功,应加上:


if ( *p == null )
{
 ...//进行申请内存失败处理
} //申请内存后一定要加上内存申请成功与否的语句,而且最后进行释放


  试题7存在与试题6同样的问题,在执行


char *str = (char *) malloc(100); 


  后未进行内存是否申请成功的判断;另外,在free(str)后未置str为空,导致可能变成一个“野”指针,应加上:


str = null; 


  试题6的test函数中也未对malloc的内存进行释放。












21下面的一段程序有什么错误:


swap( int* p1,int* p2 )
{
 int *p;
 *p = *p1;这里只是对指针所指向的内容的赋值,而不是指针赋值
 *p1 = *p2;
 *p2 = *p;



  在swap函数中,p是一个“野”指针,有可能指向系统区,导致程序运行的崩溃。在vc++中debug运行时提示错误“access violation”。该程序应该改为:
//申请指针后,同一赋值为NULL
swap( int* p1,int* p2 )
{
 int p;
 p = *p1;
 *p1 = *p2;
 *p2 = p;



22:分别给出bool,int,float,指针变量 与“零值”比较的 if 语句(假设变量名为var)


  解答:


   bool型变量:if(!var)


   int型变量: if(var==0)


   float型变量:


   const float epsinon = 0.00001;


   if ((x >= - epsinon) && (x <= epsinon)


   指针变量:  if(var==null)


  剖析:


  考查对0值判断的“内功”,bool型变量的0判断完全可以写成if(var==0),而int型变量也可以写成if(!var),指针变量的判断也可以写成if(!var),上述写法虽然程序都能正确运行,但是未能清晰地表达程序的意思。 


  一般的,如果想让if判断一个变量的“真”、“假”,应直接使用if(var)、if(!var),表明其为“逻辑”判断;如果用if判断一个数值型变量(short、int、long等),应该用if(var==0),表明是与0进行“数值”上的比较;而判断指针则适宜用if(var==null),这是一种很好的编程习惯。


  浮点型变量并不精确,所以不可将float变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。如果写成if (x == 0.0),则判为错,得0分。




23:以下为windows nt下的32位c++程序,请计算sizeof的值


void func ( char str[100] )
{
 sizeof( str ) = ?//数目名字是一个指针,指针占4个字节
}


void *p = malloc( 100 );
sizeof ( p ) = ? 


  解答:
……
sizeof( str ) = 4
sizeof ( p ) = 4 


char str[10];
cout << sizeof(str) << endl; 




24:写一个“标准”宏min,这个宏输入两个参数并返回较小的一个。另外,当你写下面的代码时会发生什么事?


least = min(*p++, b); 


  解答:


#define min(a,b) ((a) <= (b) ? (a) : (b)) 


  min(*p++, b)会产生宏的副作用




25 为什么标准头文件都有类似以下的结构? 


#ifndef __incvxworksh
#define __incvxworksh 
#ifdef __cplusplus


extern "c" {
#endif 
/*...*/ 
#ifdef __cplusplus
}


#endif 
#endif /* __incvxworksh */ 


  解答:


  头文件中的编译宏


#ifndef __incvxworksh
#define __incvxworksh
#endif 


  的作用是防止被重复引用。
为了实现c和c++的混合编程,c++提供了c连接交换指定符号extern "c"来解决名字匹配问题,函数声明前加上extern "c"后,则编译器就会按照c语言的方式将该函数编译为_foo,这样c语言中就可以调用c++的函数了。


26 编写一个函数,作用是把一个char组成的字符串循环右移n个。比如原来是“abcdefghi”如果n=2,移位后应该是“hiabcdefgh” 


  函数头是这样的:


//pstr是指向以'\0'结尾的字符串的指针
//steps是要求移动的n


void loopmove ( char * pstr, int steps )
{
 //请填充...



  解答:


  正确解答1:


void loopmove ( char *pstr, int steps )
{
 int n = strlen( pstr ) - steps;
 char tmp[max_len]; 
 strcpy ( tmp, pstr + n ); 
 strcpy ( tmp + steps, pstr); 
 *( tmp + strlen ( pstr ) ) = '\0';
 strcpy( pstr, tmp );



  正确解答2:


void loopmove ( char *pstr, int steps )
{
 int n = strlen( pstr ) - steps;
 char tmp[max_len]; 
 memcpy( tmp, pstr + n, steps ); 
 memcpy(pstr + steps, pstr, n ); 
 memcpy(pstr, tmp, steps ); 



27  static关键字至少有下列n个作用:


  (1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;


  (2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;


  (3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;




28 const关键字至少有下列n个作用:


  (1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;


  (2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;


  (3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;


  (4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;


29:请写一个c函数,若处理器是big_endian的,则返回0;若是little_endian的,则返回1


  解答:


int checkcpu()
{
 {
  union w
  { 
   int a;
   char b;
  } c;
  c.a = 1;
  return (c.b == 1);
 }



30. 堆和栈的区别?
栈区(stack)- 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
堆区(heap) - 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。


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


2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。


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


31.struct 和 class 的区别


答案:struct 的成员默认是公有的,而类的成员默认是私有的。struct 和 class 在其他方面是功能相当的。 


从感情上讲,大多数的开发者感到类和结构有很大的差别。感觉上结构仅仅象一堆缺乏封装和功能的开放的内存位,而类就象活的并且可靠的社会成员,它有智能服务,有牢固的封装屏障和一个良好定义的接口。既然大多数人都这么认为,那么只有在你的类有很少的方法并且有公有数据(这种事情在良好设计的系统中是存在的!)时,你也许应该使用 struct 关键字,否则,你应该使用 class 关键字。 


32.
#include "stdafx.h"
#define SQR(X) X*X
int main(int argc, char* argv[])
{
 int a = 10;
 int k = 2;
 int m = 1;
 a /= SQR(k+m)/SQR(k+m); 
 printf("%d\n",a); 
 return 0;
}
这道题目的结果是什么啊?   2+1*2+1/2+1*2+1=2+2+0.5+2+1=
--------------------------------------------------------------------------
33.
const 符号常量;
(1)const char *p
(2)char const *p
(3)char * const p
说明上面三种描述的区别;


如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。
(1)const char *p
一个指向char类型的const对象指针,p不是常量,我们可以修改p的值,使其指向不同的char,但是不能改变它指向非char对象,如:
const char *p;
char c1='a';
char c2='b';
p=&c1;//ok
p=&c2;//ok
*p=c1;//error
(2)char const *p
(3)char * const p
这两个好象是一样的,此时*p可以修改,而p不能修改。
(4)const char * const p
这种是地址及指向对象都不能修改。
34.下面是C语言中两种if语句判断方式。请问哪种写法更好?为什么?
 int n;
 if (n == 10) // 第一种判断方式
 if (10 == n) // 第二种判断方式
如果少了个=号,编译时就会报错,减少了出错的可能行,可以检测出是否少了=
35.写出运行结果:
{// test2
    union V {
 struct X {
  unsigned char s1:2;
  unsigned char s2:3;
  unsigned char s3:3;
 } x;
 unsigned char c;
    } v;
    v.c = 100;
    printf("%d", v.x.s3); 
}


3  //011
36.用C++写个程序,如何判断一个操作系统是16位还是32位的?不能用sizeof()函数
A1:
16位的系统下,
int i = 65536;
cout << i; // 输出0;
int i = 65535;
cout << i; // 输出-1;
32位的系统下,
int i = 65536;
cout << i; // 输出65536;
int i = 65535;
cout << i; // 输出65535;
A2:
int a = ~0;
if( a>65536 ) 
{
    cout<<"32 bit"<<endl;
}
else
{
    cout<<"16 bit"<<endl;
}
37.C和C++有什么不同?
从机制上:c是面向过程的(但c也可以编写面向对象的程序);c++是面向对象的,提供了类。但是,c++编写面向对象的程序比c容易
从适用的方向:c适合要求代码体积小的,效率高的场合,如嵌入式;c++适合更上层的,复杂的;  llinux核心大部分是c写的,因为它是系统软件,效率要求极高。
从名称上也可以看出,c++比c多了+,说明c++是c的超集;那为什么不叫c+而叫c++呢,是因为c++比c来说扩充的东西太多了,所以就在c后面放上两个+;于是就成了c++
C语言是结构化编程语言,C++是面向对象编程语言。
C++侧重于对象而不是过程,侧重于类的设计而不是逻辑的设计。
38.在不用第三方参数的情况下,交换两个参数的值
#include <stdio.h>
void main()
{
        int i=60;
        int j=50;
        i=i+j;
        j=i-j;
        i=i-j;
        printf("i=%d\n",i);
        printf("j=%d\n",j);
}
方法二:
i^=j;
j^=i;
i^=j;
方法三:
// 用加减实现,而且不会溢出
a = a+b-(b=a)
.进程间通信的方式有?
进程间通信的方式有 共享内存, 管道 ,Socket ,消息队列 ,等
39 struct A 

char t:4; 
char k:4; 
unsigned short i:8; 
unsigned long m; 

sizeof(A)=?(不考虑边界对齐)
7
40给定结构struct A 
{
      char t:4;
      char k:4;
      unsigned short i:8;
      unsigned long m;
};问sizeof(A) = ?
给定结构struct A 
{
      char t:4; 4位
      char k:4; 4位
      unsigned short i:8; 8位     
      unsigned long m; // 偏移2字节保证4字节对齐
}; // 共8字节


41下面的函数实现在一个固定的数上加上一个数,有什么错误,改正 
int add_n(int n) 

  static int i=100; 
  i+=n; 
  return i; 

答:
因为static使得i的值会保留上次的值。
去掉static就可了
42 union a {
 int a_int1;
 double a_double;
 int a_int2;
};
typedef struct
{
 a a1;
 char y;
} b;
class c
{
 double c_double;
 b b1;
 a a2;
};
输出cout<<sizeof(c)<<endl;的结果?
43 i最后等于多少?
int i = 1;
int j = i++; //j=1  i=2
if((i>j++) && (i++ == j)) i+=j;
答:
i = 5
44 unsigned short array[]={1,2,3,4,5,6,7};
int i = 3;
*(array + i) = ?
答:
4
45 试编写函数判断计算机的字节存储顺序是开序(little endian)还是降序(bigendian)
答:
bool IsBigendian()
{
 unsigned short usData = 0x1122;
 unsigned char  *pucData = (unsigned char*)&usData;
 return (*pucData == 0x22);
}
46简述Critical Section和Mutex的不同点
答:
对几种同步对象的总结
1.Critical Section
A.速度快
B.不能用于不同进程
C.不能进行资源统计(每次只可以有一个线程对共享资源进行存取)
2.Mutex
A.速度慢
B.可用于不同进程
C.不能进行资源统计
3.Semaphore
A.速度慢
B.可用于不同进程
C.可进行资源统计(可以让一个或超过一个线程对共享资源进行存取)
4.Event
A.速度慢
B.可用于不同进程
C.可进行资源统计
47 请指出下列程序中的错误并且修改
void GetMemory(char *p){
  p=(char *)malloc(100);
}
void Test(void){
  char *str=NULL;
  GetMemory=(str);
  strcpy(str,"hello world");
  printf(str);
}
A:错误--参数的值改变后,不会传回
GetMemory并不能传递动态内存,Test函数中的 str一直都是 NULL。
strcpy(str, "hello world");将使程序崩溃。
修改如下:
char *GetMemory(){
  char *p=(char *)malloc(100);
  return p;
}
void Test(void){
  char *str=NULL;
  str=GetMemory(){
  strcpy(str,"hello world");
  printf(str);
}
方法二:void GetMemory2(char **p)变为二级指针.
void GetMemory2(char **p, int num)
{
 *p = (char *)malloc(sizeof(char) * num);
}
48用C 写一个输入的整数,倒着输出整数的函数,要求用递归方法 ;
答:
void fun( int a )
{
 printf( "%d", a%10 );
 a /= 10;
 if( a <=0 )return;
 fun( a );
}
49.头文件中的 ifndef/define/endif 干什么用?预处理
答:防止头文件被重复引用


50. #i nclude 和 #i nclude “filename.h” 有什么区别?
答:前者用来包含开发环境提供的库头文件,后者用来包含自己编写的头文件。


51.在C++ 程序中调用被 C 编译器编译后的函数,为什么要加 extern “C”声明?
答:函数和变量被C++编译后在符号库中的名字与C语言的不同,被extern "C"修饰的变
量和函数是按照C语言方式编译和连接的。由于编译后的名字不同,C++程序不能直接调
用C 函数。C++提供了一个C 连接交换指定符号extern“C”来解决这个问题。
52. 回答下面的问题(6分)
(1).Void GetMemory(char **p, int num){
*p = (char *)malloc(num);
}
void Test(void){
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
请问运行Test 函数会有什么样的结果?
答:输出“hello”
(2). void Test(void){
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL){
strcpy(str, “world”);
printf(str);
}
}
请问运行Test 函数会有什么样的结果?
答:输出“world”
(3). char *GetMemory(void){
char p[] = "hello world";
return p;
}
void Test(void){
char *str = NULL;
str = GetMemory();
printf(str);
}
请问运行Test 函数会有什么样的结果?
答:无效的指针,输出不确定
53. 编写strcat函数(6分)
已知strcat函数的原型是char *strcat (char *strDest, const char *strSrc);
其中strDest 是目的字符串,strSrc 是源字符串。
(1)不调用C++/C 的字符串库函数,请编写函数 strcat
答:
char * strcat (char * dst, const char * src)
{
char * cp = dst;
while( *cp )
cp++; /* find end of dst */
while( *cp++ = *src++ ) ; /* Copy src to end of dst */
return( dst ); /* return dst */
}
(2)strcat能把strSrc 的内容连接到strDest,为什么还要char * 类型的返回值?
答:方便赋值给其他变量
54.程序什么时候应该使用线程,什么时候单线程效率高。
答:1.耗时的操作使用线程,提高应用程序响应
2.并行操作时使用线程,如C/S架构的服务器端并发线程响应用户的请求。
3.多CPU系统中,使用线程提高CPU利用率
4.改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独
立的运行部分,这样的程序会利于理解和修改。
其他情况都使用单线程。






55.TCP/IP 建立连接的过程?(3-way shake)
答:在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
  
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个
SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
56.ICMP是什么协议,处于哪一层?
答:Internet控制报文协议,处于网络层(IP层)


57 winsock建立连接的主要实现步骤?
答:服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()
等待客户端连接。
客户端:socker()建立套接字,连接(connect)服务器,连接上后使用send()和recv(
),在套接字上写读数据,直至数据交换完毕,closesocket()关闭套接字。
服务器端:accept()发现有客户端连接,建立一个新的套接字,自身重新开始等待连
接。该新产生的套接字使用send()和recv()写读数据,直至数据交换完毕,closesock
et()关闭套接字。
58 动态连接库的两种方式?
答:调用一个DLL中的函数有两种方法:
1.载入时动态链接(load-time dynamic linking),模块非常明确调用某个导出函数
,使得他们就像本地函数一样。这需要链接时链接那些函数所在DLL的导入库,导入库向
系统提供了载入DLL时所需的信息及DLL函数定位。 
2.运行时动态链接(run-time dynamic linking),运行时可以通过LoadLibrary或Loa
dLibraryEx函数载入DLL。DLL载入后,模块可以通过调用GetProcAddress获取DLL函数的
出口地址,然后就可以通过返回的函数指针调用DLL函数了。如此即可避免导入库文件了
59 IP组播有那些好处?
答:Internet上产生的许多新的应用,特别是高带宽的多媒体应用,带来了带宽的急剧
消耗和网络拥挤问题。组播是一种允许一个或多个发送者(组播源)发送单一的数据包
到多个接收者(一次的,同时的)的网络技术。组播可以大大的节省网络带宽,因为无
论有多少个目标地址,在整个网络的任何一条链路上只传送单一的数据包。所以说组播
技术的核心就是针对如何节约网络资源的前提下保证服务质量。
60.描述实时系统的基本特性
      在特定时间内完成特定的任务,实时性与可靠性。
61.全局变量和局部变量在内存中是否有区别?如果有,是什么区别?
     全局变量储存在静态数据库,局部变量在堆栈。
62.什么是平衡二叉树?
     左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于1。
63.堆栈溢出一般是由什么原因导致的?
     没有回收垃圾资源。
64.冒泡排序算法的时间复杂度是什么?
     时间复杂度是O(n^2)。
65.Internet采用哪种网络协议?该协议的主要层次结构?
     Tcp/Ip协议
     主要层次结构为: 应用层/传输层/网络层/数据链路层/物理层。
66.Internet物理地址和IP地址转换采用什么协议?
     ARP (Address Resolution Protocol)(地址解析協議)
67.IP地址的编码分为哪俩部分?
    IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。
68.不能做switch()的参数类型是:
switch的参数不能为实型。
注:必须是整数型常量,包括char,short,int,long等,不能是浮点数。


Int main()
{
Float a=3;
Switch(a)
{
Case 3:
Printf(“a”);
}
Return 0;
}


//error C2450: switch expression of type 'float' is illegal


69、局部变量能否和全局变量重名?
    答:能,局部会屏蔽全局。要用全局变量,需要使用"::"
局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。
70、如何引用一个已经定义过的全局变量?
    答:extern
    可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错。
71、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?
   答:可以,在不同的C文件中以static形式来声明同名全局变量。
   可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错。
72、语句for( ;1 ;)有什么问题?它是什么意思?
   答:无限循环,和while(1)相同。
73、do……while和while……do有什么区别?
   答:前一个循环一遍再判断,后一个判断以后再循环。
74 程序的局部变量存在于(栈)中,全局变量存在于(静态区 )中,动态申请数据存在于( 堆)中。
75、设有以下说明和定义:
typedef union {long i; int k[5]; char c;} DATE;     //25
struct data { int cat; DATE cow; double dog;} too;  //37
DATE max;
则语句 printf("%d",sizeof(struct date)+sizeof(max));的执行结果是:___52____
  62
76、队列和栈有什么区别?
   队列先进先出,栈后进先出


77、请找出下面代码中的所以错误
说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”
#include"string.h"
main()
{
 char*src="hello,world";
 char* dest=NULL;
 int len=strlen(src);
 dest=(char*)malloc(len);
 char* d=dest;
 char* s=src[len];
 while(len--!=0) 
  d++=s--;
 printf("%s",dest);
 return 0;

答:
int main(){
char* src = "hello,world";
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("%s\n",dest);
free(dest);// 使用完,应当释放空间,以免造成内存汇泄露
return 0;
}




78.用两个栈实现一个队列的功能?要求给出算法和思路!
设2个栈为A,B, 一开始均为空.
入队:
将新元素push入栈A;
出队:
(1)判断栈B是否为空;
(2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;
(3)将栈B的栈顶元素pop出;
79.对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?
c用宏定义,c++用inline


80.软件测试都有那些种类?
黑盒:针对系统功能的测试   白合:测试函数功能,各函数接口


81.进程和线程的差别。
线程是指进程内的一个执行单元,也是进程内的可调度实体.
与进程的区别:
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源. 
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。


网络编程中设计并发服务器,使用多进程 与 多线程 ,请问有什么区别?
1,进程:子进程是父进程的复制品。子进程获得父进程数据空间、堆和栈的复制品。
2,线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
两者都可以提高程序的并发度,提高程序运行效率和响应时间。
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。


82.测试方法 
人工测试:个人复查、抽查和会审
机器测试:黑盒测试和白盒测试
83.Heap与stack的差别。
Heap是堆,stack是栈。
Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。
Stack空间有限,Heap是很大的自由存储区
C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符。
程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行




84 一语句实现x是否为2的若干次幂的判断
int i = 512;
 ((i & (i - 1)) ? false : true);


85 main()
{
 int a[5]={1,2,3,4,5};
  int *ptr=(int *)(&a+1);
   printf("%d,%d",*(a+1),*(ptr-1));
}
输出:2,5


85 char* s="AAA";
printf("%s",s);
s[0]='B';
printf("%s",s);
有什么错?
"AAA"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。
cosnt char* s="AAA";
然后又因为是常量,所以对是s[0]的赋值操作是不合法的。


86 列举几种进程的同步机制,并比较其优缺点。
  原子操作 
信号量机制
  自旋锁
  管程,会合,分布式系统
87.进程之间通信的途径
共享存储系统
消息传递系统
管道:以文件系统为基础
88.进程死锁的原因
资源竞争及进程推进顺序非法
89.死锁的4个必要条件
互斥、请求保持、不可剥夺、环路
90.死锁的处理
鸵鸟策略、预防策略、避免策略、检测与解除死锁
91.  操作系统中进程调度策略有哪几种?
FCFS(先来先服务),优先级,时间片轮转,多级反馈




92.数组和链表的区别
数组:数据顺序存储,固定大小
连表:数据可以随机存储,大小可动态改变
93.ISO的七层模型是什么?tcp/udp是属于哪一层?tcp/udp有何优缺点?
应用层
表示层
会话层
运输层
网络层
物理链路层
物理层
tcp /udp属于运输层
TCP 服务提供了数据流传输、可靠性、有效流控制、全双工操作和多路复用技术等。
与 TCP 不同, UDP 并不提供对 IP 协议的可靠机制、流控制以及错误恢复功能等。由于 UDP 比较简单, UDP 头包含很少的字节,比 TCP 负载消耗少。
tcp: 提供稳定的传输服务,有流量控制,缺点是包头大,冗余性不好
udp: 不提供稳定的服务,包头小,开销小  




94:(void *)ptr 和 (*(void**))ptr的结果是否相同?其中ptr为同一个指针
.(void *)ptr 和 (*(void**))ptr值是相同的


95,要对绝对地址0x100000赋值,我们可以用
(unsigned int*)0x100000 = 1234;
那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
*((void (*)( ))0x100000 ) ( );


96分析 typedef struct AA
{
       int b1:5;
       int b2:2;
}AA;
void main()
{
       AA aa;
       char cc[100];
        strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");
      memcpy(&aa,cc,sizeof(AA));
       cout << aa.b1 <<endl;
       cout << aa.b2 <<endl;
}
答案是 -16和1


97分析:
struct bit 
{  int a:3; 
   int b:2; 
   int c:3; 
}; 
int main() 

 bit s; 
 char *c=(char*)&s; 
  cout<<sizeof(bit)<<endl;
 *c=0x99;
  cout << s.a <<endl <<s.b<<endl<<s.c<<endl; 
    int a=-1;
  printf("%x",a);
 return 0; 

输出为什么是  1001 1001
4
1
-1
-4
ffffffff




98改错:
#i nclude <stdio.h>
int main(void) {
    int **p;
   int arr[100];
    p = &arr;
    return 0;
}
解答:
搞错了,是指针类型不同,
int **p; //二级指针
&arr; //得到的是指向第一维为100的数组的指针
#i nclude <stdio.h>
int main(void) {
int **p, *q;
int arr[100];
q = arr;
p = &q;
return 0;
}


99下面这个程序执行后会有什么错误或者效果:
 #define MAX 255
 int main()
{
  unsigned char A[MAX],i;//i被定义为unsigned char
  for (i=0;i<=MAX;i++)
     A[i]=i;
}
解答:死循环加数组越界访问(C/C++不进行数组越界检查)




100 struct name1{
  char str;
  short x;
  int  num;
}
struct name2{
  char str;
  int num;
  short x;
}
sizeof(struct name1)=8,sizeof(struct name2)=12




101读文件file1.txt的内容(例如):
12
34
56
输出到file2.txt:
56
34
12
(逆序)
2)输出和为一个给定整数的所有组合
例如n=5
5=1+4;5=2+3(相加的数不能重复)
则输出
1,4;2,3。
注意可增长数组的应用.
#i nclude <stdio.h>
#i nclude <stdlib.h>
int main(void)
{
        int MAX = 10;
int *a = (int *)malloc(MAX * sizeof(int));
int *b;
   
FILE *fp1;
FILE *fp2;
fp1 = fopen("a.txt","r");
if(fp1 == NULL)
{printf("error1");
   exit(-1);
}
    fp2 = fopen("b.txt","w");
if(fp2 == NULL)
{printf("error2");
   exit(-1);
}
int i = 0;
   int j = 0;
while(fscanf(fp1,"%d",&a[i]) != EOF)
{
i++;
j++;
if(i >= MAX)
{
MAX = 2 * MAX;
b = (int*)realloc(a,MAX * sizeof(int));
if(b == NULL)
{
printf("error3");
exit(-1);
}
a = b;
}
}
for(;--j >= 0;)
  fprintf(fp2,"%d\n",a[j]);
fclose(fp1);
fclose(fp2);
return 0;
}




102 一个递规反向输出字符串的例子,经典例程.
void inverse(char *p)
{
   if( *p = = '\0' ) 
return;
   inverse( p+1 );
   printf( "%c", *p );
}
int main(int argc, char *argv[])
{
   inverse("abc\0");
    return 0;
}




103、用递归算法判断数组a[N]是否为一个递增数组。
递归的方法,记录当前最大的,并且判断当前的是否比这个还大,大则继续,否则返回false结束:
bool fun( int a[], int n )
{
if( n= =1 )
return true;
if( n= =2 )
return a[n-1] >= a[n-2];
return fun( a,n-1) && ( a[n-1] >= a[n-2] );
}




104 什么是可重入性?
可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。相反,不可重入(non-reentrant)函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。


105 可重入函数:
不为连续的调用持有静态数据。
不返回指向静态数据的指针;所有数据都由函数的调用者提供。
使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。
如果必须访问全局变量,记住利用互斥信号量来保护全局变量。
绝不调用任何不可重入函数。;


106.用最简单的方法实现函数int strcmp(char *p1,char *p2)
int ret;
//while( *p1 && *p2 && !(ret=*p1-*p2) )
while(!(ret=*p1-*p2) && *p1 && *p2)
{
p1++;p2++;
}
return ret;
int strcmp(const char * cs,const char * ct)
{
register signed char __res;


while (1) {
if ((__res = *cs - *ct++) != 0 || !*cs++)
break;
}


return __res;
}


107什么是预编译,何时需要预编译: 
答案: 
1、总是使用不经常改动的大型代码体。 
2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。 
108 char * const p      char const * p      const char *p 上述三个有什么区别? 
答案: 
char * const p; //常量指针,p的值不可以修改 
char const * p;//指向常量的指针,指向的常量值不可以改 const char *p; //和char const *p 
109 char str1[] = "abc"; char str2[] = "abc"; const char str3[] = "abc"; const char str4[] = "abc"; const char *str5 = "abc"; const char *str6 = "abc"; char *str7 = "abc"; char *str8 = "abc"; cout < < ( str1 == str2 ) < < endl; cout < < ( str3 == str4 ) < < endl; cout < < ( str5 == str6 ) < < endl; cout < < ( str7 == str8 ) < < endl; 
结果是:0 0 1 1 str1,str2,str3,str4是数组变量,它们有各自的内存空间;而str5,str6,str7,str8是指针,它们指向相同的常量区域。 


110以下代码中的两个sizeof用法有问题吗? 
void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母 
{    
for( size_t i=0; i <sizeof(str)/sizeof(str[0]); ++i )        
if( 'a' <=str[i] && str[i] <='z' )            
str[i] -= ('a'-'A' );

char str[] = "aBcDe";
cout < < "str字符长度为: " < < sizeof(str)/sizeof(str[0]) < < endl; 
UpperCase( str );
cout < < str < < endl; 


答案:函数外的str是一个静态定义的数组,因此其大小为6,因为还有'\0',
函数内的str返回4。 


111一个32位的机器,该机器的指针是多少位答案: 
指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线。所以指针的位数就是4个字节了。 
112。
main() 
{  
int a[5]={1,2,3,4,5};    
int *ptr=(int *)(&a+1);    
printf("%d,%d",*(a+1),*(ptr-1)); 
} 答案:2。5 


113。请问以下代码有什么问题:
int  main()
{
 char a;
 char *str=&a;
 strcpy(str,"hello");
 printf(str); 
return 0; 
} 答案:没有为str分配内存空间,将会发生异常问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。 
114。
char* s="AAA";
printf("%s",s); 
s[0]='B'; 
printf("%s",s); 
有什么错?
答案:"AAA"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。 cosnt char* s="AAA"; 然后又因为是常量,所以对是s[0]的赋值操作是不合法的。 


115。写一个“标准”宏,这个宏输入两个参数并返回较小的一个。
答案:.#define Min(X, Y) ((X)>(Y)?(Y):(X))  //结尾没有‘;’ 
116。嵌入式系统中经常要用到无限循环,你怎么用C编写死循环。答案:while(1){}或者for(;;) 
117。关键字static的作用是什么?答案:定义静态变量 
118。关键字const有什么含意?答案:表示常量不可以修改的变量。 


119。关键字volatile有什么含意?并举出三个不同的例子?
答案:一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 
1). 并行设备的硬件寄存器(如:状态寄存器) 
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 
3). 多线程应用中被几个任务共享的变量 
 
120。int (*s[10])(int) 表示的是什么啊?
答案:int (*s[10])(int) 函数指针数组,每个指针指向一个int func(int param)的函数。 


121。有以下表达式: 
int a=248;  int b=4; 
int const c=21;  const int *d=&a;  
int *const e=&b;  int const *f const =&a; 
请问下列表达式哪些会被编译器禁止?为什么? *c=32;d=&b;*d=43;e=34;e=&a;f=0x321f; 
答案:
*c 这是个什么东东,禁止 *d 说了是const, 禁止 e = &a 说了是const , 
禁止 const *f const =&a; 禁止 
122交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3; 答案:有两种解法, 一种用算术算法, 一种用^(异或)
 a = a + b; b = a - b; a = a - b; 
or a = a^b; b = a^b; a = a^b; or a ^= b ^= a;  // 只能对int,char.
123.c和c++中的struct有什么不同?
答案:c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private 
124.进程之间通信的途径答案:共享存储系统消息传递系统管道:以文件系统为基础 
125.进程死锁的原因答案:资源竞争及进程推进顺序非法 
126.死锁的4个必要条件答案:互斥、请求保持、不可剥夺、环路 
127.死锁的处理答案:鸵鸟策略、预防策略、避免策略、检测与解除死锁 
128.  操作系统中进程调度策略有哪几种?答案:FCFS(先来先服务),优先级,时间片轮转,多级反馈 
129.类的静态成员和非静态成员有何区别?答案:类的静态成员每个类只有一个,非静态成员每个对象一个 
130.纯虚函数如何定义?使用时应注意什么?答案:virtual void f()=0; 是接口,子类必须要实现 
131.数组和链表的区别答案:数组:数据顺序存储,固定大小连表:数据可以随机存储,大小可动态改变 
132.ISO的七层模型是什么?tcp/udp是属于哪一层?tcp/udp有何优缺点?
答案:
应用层,表示层,会话层,运输层,网络层,物理链路层,物理层 
tcp /udp属于运输层 
TCP 服务提供了数据流传输、可靠性、有效流控制、全双工操作和多路复用技术等。与 TCP 不同, UDP 并不提供对 IP 协议的可靠机制、流控制以及错误恢复功能等。由于 UDP 比较简单, UDP 头包含很少的字节,比 TCP 负载消耗少。 
tcp: 提供稳定的传输服务,有流量控制,缺点是包头大,冗余性不好 
udp: 不提供稳定的服务,包头小,开销小  


133:(void *)ptr 和 (*(void**))ptr的结果是否相同?其中ptr为同一个指针
答案:.(void *)ptr 和 (*(void**))ptr值是相同的 
134:
int main()    
{    int x=3;    printf("%d",x);    return 1;      } 问函数既然不会被其它函数调用,为什么要返回1?
答案:mian中,c标准认为0表示成功,非0表示错误。具体的值是某中具体出错信息 
136,已知一个数组table,用一个宏定义,求出数据的元素个数’
答案:
 #define NTBL (sizeof(table)/sizeof(table[0])) 


137 . -1,2,7,28,,126请问28和126中间那个数是什么?为什么?
答案:答案应该是4^3-1=63 规律是n^3-1(当n为偶数0,2,4)      n^3+1(当n为奇数1,3,5) 
138。对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现? 
答案:c用宏定义,c++用inline 
139。直接链接两个信令点的一组链路称作什么? 答案:PPP点到点连接 
140。软件测试都有那些种类? 答案:黑盒:针对系统功能的测试    白合:测试函数功能,各函数接口 
141。确定模块的功能和模块的接口是在软件设计的那个队段完成的? 答案:概要设计阶段 
142。enum string    {    x1,    x2,    x3=10,    x4,    x5,    }x;    问x;
答案:取值在0。1。10。11。12中的一个 


143。
unsigned char *p1;    unsigned long *p2;    
p1=(unsigned char *)0x801000;    
p2=(unsigned long *)0x810000;    
请问p1+5=  ;        p2+5=  ; 
答案:801005;810014。不要忘记了这个是16进制的数字,p2要加20变为16进制就是14 


:  
144.Ethternet链接到Internet用到以下那个协议? B  
A.HDLC;B.ARP;C.UDP;D.TCP;E.ID  
145.属于网络层协议的是: A  
A.TCP;B.IP;C.ICMP;D.X.25  
146.Windows消息调度机制是: C  
A.指令队列;B.指令堆栈;C.消息队列;D.消息堆栈; 


147.请问下面程序有什么错误?    
int a[60][250][1000],i,j,k;    
for(k=0;k <=1000;k++)    
for(j=0;j <250;j++)      
for(i=0;i <60;i++)      
a[i][j][k]=0; 
答案:把循环语句内外换一下 


148。以下是求一个数的平方的程序,请找出错误:    
#define SQUARE(a)  ((a)*(a))    
int a=5;    int b;    
b=SQUARE(a++); 
答案:这个没有问题,s(a++),就是((a++)×(a++))唯一要注意的就是计算后a=7了 


149。
typedef unsigned char BYTE      
int examply_fun(BYTE gt_len; BYTE *gt_code)      
{        
BYTE *gt_buf;      gt_buf=(BYTE *)MALLOC(Max_GT_Length);      ......      if(gt_len>Max_GT_Length)        
{        
return GT_Length_ERROR;          
}       
 .......      
} 答案:要释放内存问答题: 


150.TCP/IP通信建立的过程怎样,端口有什么作用?
答案:三次握手,确定是哪个应用程序使用该协议 


151、局部变量能否和全局变量重名?
答案:能,局部会屏蔽全局。要用全局变量,需要使用"::"   局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内 
152、如何引用一个已经定义过的全局变量?
答案:extern 可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错 
153、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?答案:可以,在不同的C文件中以static形式来声明同名全局变量。可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错 


154、static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
答案:全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。 static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件 static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用; static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值; static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝 


155、判断题(对的写T,错的写F并说明原因,每小题4分,共20分) 
1、有数组定义int a[2][2]={{1},{2,3}};则a[0][1]的值为0。(    正确 ) 
2、int (*ptr) (),则ptr是一维数组的名字。(错误  int (*ptr) ();定义一个指向函数的指针变量    ) 
3、指针在任何情况下都可进行>, <,>=, <=,==运算。(  错误  ) 
4、switch(c) 语句中c可以是int ,long,char ,float ,unsigned int 类型。(  错,不能用实形 ) 
156、填空题(共30分) 
1、在windows下,写出运行结果,每空2分,共10分。 
char str[ ]= "Hello"; char *p=str; int n=10; sizeof(str)=(      ) sizeof(p)=(      ) sizeof(n)=(      ) void func(char str[100]){    } sizeof(str)=(    )  
答案:6,4,4,4, 
156、  不使用库函数,编写函数int strcmp(char  *source, char *dest) 相等返回0,不等返回-1; 
答案:一、
int strcmp(char  *source, char *dest) 
{  
assert((source!=NULL)&&(dest!=NULL));  
int i,j;  
for(i=0; source[i]==dest[i]; i++)  
{  
if(source[i]=='\0' && dest[i]=='\0')    
return 0; 
else    
return -1;  




答案:二、 
int strcmp(char *source, char *dest)
{    while ( (*source != '\0') && (*source == *dest))   
 {
 source++; dest++;    
}    
return ( (*source) - (*dest) ) ? -1 : 0;
 } 


157写一函数int fun(char *p)判断一字符串是否为回文,是返回1,不是返回0,出错返回-1 
答案:一、 
int fun(char *p)
{  if(p==NULL)  
return -1;  
else  
{  int length = 0;  int i = 0;  int judge = 1;  length = strlen(p);  
for(i=0; i <length/2; i++)  
{    if(p[i]!=p[length-1-i])   
 judge = 0;    
break;  
}  
if(judge == 0)    
return 0;  
else    
return 1;  


答案:二、 
int fun(char *p)

int len = strlen(p) - 1;
char *q = p + len; 
if (!p) return -1;
while (p < q) 

if ((*p++) != (*q--)) 
return 0; 

return 1;
}  


158
1.在OSI 7 层模型中,网络层的功能有( B) 
A.确保数据的传送正确无误  B.确定数据包如何转发与路由 C.在信道上传送比特流    D.纠错与流控 
2.FDDI 使用的是___局域网技术。(C ) 
A.以太网;    B.快速以太网;    C.令牌环;    D.令牌总线。
注: (光纤分布数据接口(FDDI)是目前成熟的LAN技术中传输速率最高的一种)
3.下面那种LAN 是应用CSMA/CD协议的(C) 
A.令牌环    B.FDDI    C.ETHERNET    D.NOVELL 
4.TCP 和UDP 协议的相似之处是 (C ) 
A.面向连接的协议    B.面向非连接的协议    C.传输层协议    D.以上均不对 
5.应用程序PING 发出的是___报文.(C )
 A.TCP 请求报文。    B.TCP 应答报文。    C.ICMP 请求报文。  D.ICMP 应答报文。 
6.以下说法错误的是(多) (BD ) 
A.中继器是工作在物理层的设备    B.集线器和以太网交换机工作在数据连路层 C.路由器是工作在网络层的设备    D.桥能隔离网络层广播 
7.当桥接收的分组的目的MAC地址在桥的映射表中没有对应的表项时,采取的策略是( C)
 A.丢掉该分组  B.将该分组分片    C.向其他端口广播该分组    D.以上答案均不对 
8.LAN Switch 在网络层次模型中的地位( B) 
A.物理层    B.链路层    C.网络层    D.以上都不是 
9.小于___的TCP/UDP端口号已保留与现有服务一一对应,此数字以上的端口号可自由分配。( C) 
A.199      B.100    C.1024      D.2048 
10.当一台主机从一个网络移到另一个网络时,以下说法正确的是 (B ) 
A.必须改变它的IP 地址和MAC 地址    B.必须改变它的IP 地址,但不需改动MAC 地址 C.必须改变它的MAC 地址,但不需改动IP 地址    D.MAC 地址.IP 地址都不需改动


159. 找错 
#define MAX_SRM 256 
DSNget_SRM_no() 
{    
static int SRM_no;    
int I;    
for(I=0;I <MAX_SRM;I++,SRM_no++)  
{    
SRM_no %= MAX_SRM;    
if(MY_SRM.state==IDLE)    
{      break;    }  
}  
if(I>=MAX_SRM)    
return (NULL_SRM);  
else    
return SRM_no; 

答: 1,SRM_no没有赋初值 
2,由于static的声明,使该函数成为不可重入(即不可预测结果)函数,因为SRM_no变量放在程序的全局存储区中,每次调用的时候还可以保持原来的赋值。这里应该去掉static声明。 
160. 写出程序运行结果 
int sum(int a) 
{    auto int c=0;    static int b=3;  c+=1;  b+=2;  return(a+b+c); }  
void main() 
{    int I;  int a=2; 
 for(I=0;I <5;I++)  
{    printf("%d,", sum(a));  } 
} 答:8,10,12,14,16 该题比较简单。只要注意b声明为static静态全局变量,其值在下次调用时是可以保持住原来的赋值的就可以。 
161 int func(int a) 
{    int b;    
switch(a)    
{        
case 1: b=30;        
case 2: b=20;        
case 3: b=16;       
default: b=0;   
}    
return b; 
} 则func(1)=? 答:func(1)=0,因为没有break语句,switch中会一直计算到b=0。这是提醒我们不要忘了break 
162:  int a[3];  a[0]=0; a[1]=1; a[2]=2;  int *p, *q;  p=a;  q=&a[2]; 则a[q-p]=? 
答:a[q-p]=a[2]=2;这题是要告诉我们指针的运算特点 
163. 定义 int **a[3][4], 则变量占有的内存空间为:_____ 
答:此处定义的是指向指针的指针数组,对于32位系统,指针占内存空间4字节,因此总空间为3×4×4=48。


164.设有int a=3;则执行语句a+=a-=a*a;后
变量a的值是?  
答案:-12
165. Struct RegX
{
long bzy:1;
long wrt:1;
   long rd:1;
long cnt:4;
long rsd:25;
};
Sizeof(RegX)=?
答案:4


166 
Char a[]=“hello\0”;
Char al[7]=“hello”;
Char *ps=“hello”;
Strlen(a)= ? Strlen(a1)= ? Strlen(ps)= ?
Sizeof(a)= ? Sizeof(a1)= ? Sizeof(ps)= ?


5 5 5 ,7 7 4 
167.对于下面的函数,要求打印出”hello”,子程序完全正确的是_(1)(3)_, 一定能打印出”hello”的是_(1)(3)(4)_,有错误的是__(2)(4)
char *GetHellostr(void);
int main(void)
{
char *ps;
ps= GetHellostr( );
if(ps != NULL)
{
printf(ps);
}
return 0;
}
(1)
char *GetHellostr(void)
{
char *ps=“hello”;
return ps;
}
(2)
char *GetHellostr(void)
{
    char a[]=“hello”;
return (char *)a;
}






(3)
char *GetHellostr(void)
{
static char a[]=“hello”;
return (char *)a;
}
(4)
char *GetHellostr(void)
{
char *ps;
ps = malloc(10);
if(NULL ==ps) return NULL;
strcpy(ps,”hello”);
return ps;
}


168.
void foo(void)
{
unsigned int a;
int  b = -7;
a=6;
(a+b>6)? puts(“>6”):puts(“<=b”);
a=8;
(a+b>8)? puts(“>8”):puts(“<=8”);
}
些函数执行结果是?  > 6  <=8
169.
下面程序分别只改到一处,就OK了,要求打印出”welcome to  huawei”
(1)
void main(void)
{
char str1[]=“welcome”;
char str2[]=“to”;
char str3[]=“huawei”;
char str[50];

memcpy(str,str1,sizeof(str1));
memcpy(str+sizeof(str1),str2,sizeof(str2));
memcpy(str+strlen(str1)+strlen(str2), str3,sizeof(str3));
printf(str);


}
(2)
void main(void)
{
char str1[]=“welcome”;
char str2[]=“to”;
char str3[]=“huawei”;
char str[50];

memcpy(str,str1, strlen(str1));
memcpy(str+strlen(str1),str2, strlen(str2));
memcpy(str+strlen(str1)+strlen(str2), str3, strlen(str3));
printf(str);


}






170
Struct tag
{
short c;
long b;
char d;
long a;
}
Sizeof(tag)可能的值?
171.找出程序中的所有错误
//分配len的长度的内存,内存地址由ptr输出
void test_malloc(char **prt, int len)
{
char *tmp=NULL;
tmp=(char*)malloc(len);
*prt=tmp;
}


void main(void)
{
char *str=“welcome to huawei”;
char *buf;
char c=0xff;
test_malloc(&buf, sizeof(str));//strlen(str)+1
if(buf ==NULL)//(NULL == buf)
{
return;
}
strcpy(buf , str);
if( c==(char)0xff)
{
printf(“OK,str=%s”,buf);
}
else
{
printf(“OH my God!”);
}
free(buf);
}


172.问题
union a {
 int a_int1;
 double a_double;
 int a_int2;
};
  typedef struct
{
 a a1;
 char y;
} b;
问题sizeof(b)  ?


173:下面这个程序执行后会有什么错误或者效果:
 #define MAX 255
 int main()
{
   unsigned char A[MAX],i;
   for (i=0;i<=MAX;i++)
     A[i]=i;
}


174, 用递归法将整数转化为符串?
Void convert( int n )
{ int i;
Char c;
if ((i=n/10)!=0)
   convert(i);
c=n%10 +’0’;
cout<<” “<<c;
}


175 用折半查找法求一个数? 数组a已按从小到大的顺序排列


while((!sign) && (bott <= top))
{
mid=(bott + top)/2;
     if(number ==a[mid])
{
local=mid;
printf(“the local is %d\n”,local);
printf(“the number is%d\n”, number);
sign =true;
}
else if(number <a[min])
   top = mid -1;
else
   bott=mid+1;
}


176 有一个字符串,将字符串从第m个字符开始全部复制到另一个新字符串?
void copystr( char *p1, char *p2, int m)
{
int n=0;
while(m<m-1)
{
n++;
p1++;
}
while(*p1 !=’/0’)
{
*p2=*p1;
p1++;
p2++;
}
*p2=’/0’;
}


177 排序问题?
问题一:写出冒泡排序
void pop_sort(int a[],int N)
{ int tmp, i , j;
for(j=0; j<N; j++)
for( i=0; i<9-j; i++)
if( a[i]>a[i+1])
{tmp=a[i];
a[i]=a[i+1];
a[i+1]=tmp;
}
}


问题一:写出选择法排序
void select_sort(int a[],int N)
{ int  i , j, k, t;
for(i=0; i<N; i++)
{
k=i;
   for( j=i+1; j<N; j ++)
if( a[j]<ak])
  k=j;
tmp=a[k];
a[k]=a[i];
a[i]=tmp;
}
}




链表问题汇总
178写一函数creat, 用来建立一个动态链表,各结点数据由键盘输入。
struct student
 {
  long num;
  float score;
  stuent *next;
 };
 
 student *creat (void)
 {
  student *head;
  student *p1=null,*p2=null;
  int n=0;
  p1=p2=new student;
  cin>>p1->num>>p1->score;
  head=null;
  while(p1->num !=0)
  {
  n=n+1;
  if(1==n) head=p1;
  else  
  p2->next=p1;
  p2=p1;
  p1= new student;
  cin>>p1->mum>>p1->score;
  }
  p2->next =NULL;
  return (head);
 }
 
179,写一print函数,将链表中的各数据遍历输出
  void print(student *head )
  {
   student *p;
   cout<<"there"<<n<<"records"<<endl;
   p=head;
   if(head!=NULL)
   do
   {
   cout<<p->num<<" "<<p->score<<endl;
   p=p->next;
   }while(p!=NULL)
  }
 
 180.写一del函数,用来删除动态链表中,指定的结点数据
 void *del(student *head, long num)
 {
  student *p1,*p2;
  if(head==NULL)
  {return (head);}
  p1=head;
  while(num!=p1->num && p1->next !=NULL)
  {
  p2=p1;
  p1=p1->next;
  }
  if(num == p1->num)
  {
  if(p1==head)
  head=p1->next;
  else
  p2->next=p1->next;
  cout<<"delete:"<<num<<endl;
  n=n-1;
  }
  else
  cout<<"can not find"<<num;
  return(head);
 }
 181 写一函数insert,用来向动态链表插入一结点
 Student *insert(student *head, student *stud)
 {
  student *p0 ,*p1, *p2;
  p1=head;
  p0=stud;
  if(head == NULL)
  {
  head=p0;
  p0->next=NULL;
  }
  else
  {
  while((p0->num >p1->num) && (p1->next!=NULL) )
  {
  p2=p1;
  p1=p1->next;
  }
  if(p0->num <= p1->num)
  {
  if(head ==p1)
  head=p0;
  else
  p2->next=p0;
  p0->next=p1;
  }
  else
  {
  p1->next=p0;
  p0->next=NULL;
  }
  }
  n=n+1;
  return(head);
  
 }




182 链表题:一个链表的结点结构
struct Node
{
int data ;
Node *next ;
};
typedef struct Node Node ;
(1)已知链表的头结点head,写一个函数把这个链表逆序 ( Intel)


Node * ReverseList(Node *head) //链表逆序
{
if ( head == NULL || head->next == NULL )
return head;
Node *p1 = head ;
Node *p2 = p1->next ;
Node *p3 = p2->next ;
p1->next = NULL ;
while ( p3 != NULL )
{
p2->next = p1 ;
p1 = p2 ;
p2 = p3 ;
p3 = p3->next ;
}
p2->next = p1 ;
head = p2 ;
return head ;
}
(2)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序。(保留所有结点,即便大小相同)
Node * Merge(Node *head1 , Node *head2)
{
if ( head1 == NULL)
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
Node *p1 = NULL;
Node *p2 = NULL;
if ( head1->data < head2->data )
{
head = head1 ;
p1 = head1->next;
p2 = head2 ;
}
else
{
head = head2 ;
p2 = head2->next ;
p1 = head1 ;
}
Node *pcurrent = head ;
while ( p1 != NULL && p2 != NULL)
{
if ( p1->data <= p2->data )
{
pcurrent->next = p1 ;
pcurrent = p1 ;
p1 = p1->next ;
}
else
{
pcurrent->next = p2 ;
pcurrent = p2 ;
p2 = p2->next ;
}
}
if ( p1 != NULL )
pcurrent->next = p1 ;
if ( p2 != NULL )
pcurrent->next = p2 ;
return head ;
}
(3)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序,这次要求用递归方法进行。 (Autodesk)
答案:
Node * MergeRecursive(Node *head1 , Node *head2)
{
if ( head1 == NULL )
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
if ( head1->data < head2->data )
{
head = head1 ;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2 ;
head->next = MergeRecursive(head1,head2->next);
}
return head ;
}




183.利用链表实现将两个有序队列A和B合并到有序队列H中,不准增加其他空间。
请提供全一点的程序
以升序为例:
while(a != NULL && b!= NULL)
{
if (a->data < b->data)
{
h->data = a->data;
a = a->next;
}
else if (a->data == b->data)
{
h->data = a->data;
a = a->next;
b = b->next;
}
else
{
h->data = b->data;
b = b->next
}
h = h->next;
}
if (a == NULL)
{
while (b != NULL)
{
h->data = b->data;
h = h->next;
b = b->next;
}
}
else 
{
while(a != NULL)
{
h->data = a->next;
h = h->next;
a = a->next;
}
}
184单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题。比如一个链表是这样的: 1->2->3->4->5 通过反转后成为5->4->3->2->1。最容易想到的方法遍历一遍链表,利用一个辅助指针,存储遍历过程中当前指针指向的下一个元素,然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。源代码如下:
struct linka {
     int data;
     linka* next;
};


void reverse(linka*& head)
{
     if(head ==NULL)
          return;
     linka*pre, *cur, *ne;
     pre=head;
     cur=head->next;
     while(cur)
     {
          ne = cur->next;
          cur->next = pre;
          pre = cur;
          cur = ne;
     }
     head->next = NULL;
     head = pre;
}
还有一种利用递归的方法。这种方法的基本思想是在反转当前节点之前先调用递归函数反转后续节点。源代码如下。不过这个方法有一个缺点,就是在反转后的最后一个结点会形成一个环,所以必须将函数的返回的节点的next域置为NULL。因为要改变head指针,所以我用了引用。算法的源代码如下:
linka* reverse(linka* p,linka*& head)
{
     if(p == NULL || p->next == NULL)
     {
          head=p;
          return p;
     }
     else
     {
          linka* tmp = reverse(p->next,head);
          tmp->next = p;
          return p;
     }
}


185 对如下双链表
typedef struct _node
{
int iData;
struct _node *pPrev;
struct _node *pNext;
}node;
a.请写出代码,将node*n插入到node*p后。
b.如果多线程同时访问此链表,需要加锁,请说明以下步骤
(a)申请内存给n.
(b)N数据初始化。
(c)插入
注意加锁和解锁的时机。
node* insert(node* p, node* n)
{
if ((p == NULL) || (n == NULL))
{
return NULL;
}


if (p->pNext != NULL)
{
p->pNext->pPrev = n;
}


n->pPrev = p;
n->pNext = p->pNext;
p->pNext = n;


return n;
}




186、试创建二叉数,并写出常见的几种遍历方式 ?
#include "stdio.h"
#include "string.h"
#include <stdlib.h>
#define NULL 0
typedef struct BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;


BiTree Create(BiTree T){
    char ch;
    ch=getchar();
    if(ch=='0')
T=NULL;
    else{
if(!(T=(BiTNode *)malloc(sizeof(BiTNode))))
    printf("Error!");
T->data=ch;
T->lchild=Create(T->lchild);
T->rchild=Create(T->rchild);
    }
    return T;
}


void Preorder(BiTree T){
     if(T){
printf("%c",T->data);
Preorder(T->lchild);
Preorder(T->rchild);
}
}//先序遍历


void Inorder(BiTree T){
    if(T){
Inorder(T->lchild);
printf("%c",T->data);
Inorder(T->rchild);
}
}//中序遍历


void Postorder(BiTree T){
    if(T){
Postorder(T->lchild);
Postorder(T->rchild);
printf("%c",T->data);
}
}//后序遍历




187、 前序遍历输入,如图所示,写出后序遍历输出结果?
 例如二叉树:
 


 
输入序列ABD..EH...CF.I..G..
输出结果为:?


答案:
输出结果为:DHEBIFGCA



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值