C语言高级测试(一)

  C语言高级测试(一)

原文出处:

http://www.programmersheaven.com/articles/pathak/article2.htm

原文有些微小的错误,我已经将之改正.

整个测试遵循以下的约定:

u       假定在所有的程序中必须的头文件都已经被正确包含。

考虑如下的数据类型:

u       char 1个字节

u       int 4个字节

u       long int 4个字节

u       float 4个字节

u       double 为个8字节

u       long double 8个字节

u       指针为4个字节

 

 

1. Consider the following program:

#include<setjmp.h>

static jmp_buf  buf;

 

main()

{

  volatile  int b;

  b =3;

 

  if(setjmp(buf)!=0) 

  {

    printf("%d ", b); 

    exit(0);

  }

  b=5;

  longjmp(buf , 1);

}

The output for this program is: 

(a) 3
(b) 5
(c) 0
(d) None of the above

解答:这是一道关于C语言中异常处理机制的题目。setjmp函数用于保存程序的运行时的堆栈环境,接下来的其它地方,你可以通过调用longjmp函数来恢复先前被保存的程序堆栈环境。longjmp函数用于恢复先前程序中调用的setjmp函数时所保存的堆栈环境。setjmplongjmp组合一起使用时,它们能提供一种在程序中实现“非本地局部跳转”("non-local goto")的机制。在调用longjmp之后,通过setjmp所返回的控制流中,例程中寄存器类型的变量将不会被恢复。

2. Consider the following program:

main()

{

   struct node

   {

     int a;

     int b;

     int c;    

   };

   struct node  s= { 3, 5,6 };

   struct node *pt = &s;

   printf("%d" ,  *(int*)pt);

}

The output for this program is:
(a) 3
(b) 5
(c) 6
(d) 7

3. Consider the following code segment:

int  foo ( int x , int  n)

{

  int val;

  val =1;

 

  if (n>0)

  {

    if (n%2 == 1)  val = val *x;

   

    val = val * foo(x*x , n/2);

  }

  return val;

}

What function of x and n is compute by this code segment?  

(a) x^n
(b) x*n
(c) n^x
(d) None of the above

4. Consider the following program:

main()

{

  int  a[5] = {1,2,3,4,5};

  int *ptr =  (int*)(&a+1);

 

  printf("%d %d" , *(a+1), *(ptr-1) );

 

}

The output for this program is:

(a) 2 2
(b) 2 1
(c) 2 5
(d) None of the above

解答*(a+1)就是a[1]*(ptr-1)就是a[4],执行结果是25

&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5int

int *ptr=(int *)(&a+1);

ptr实际是&(a[5]),也就是a+5

原因如下:

&a是数组指针,其类型为 int (*)[5];

而指针加1要根据指针类型加上一定的值,

不同类型的指针+1之后增加的大小不同

a是长度为5int数组指针,所以要加 5*sizeof(int)

所以ptr实际是a[5]

但是prt(&a+1)类型是不一样的(这点很重要)

所以prt-1只会减去sizeof(int*)

a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].

5. Consider the following program:

void foo(int [][3] );    

 

main()

{

  int a [3][3]= { { 1,2,3} , { 4,5,6},{7,8,9}};

  foo(a);

  printf("%d" , a[2][1]);

}

 

void foo( int b[][3])

{

  ++ b;

  b[1][1] =9;

}

The output for this program is:
(a) 8
(b) 9
(c) 7
(d) None of the above

解答:该题考察的是数组和指针的相关知识点。数组作为参数传递时,其退化为一个指针,该指针的指向的类型为所传递的数组类型。

6. Consider the following program:

main()

{

  int a, b,c, d;

  a=3;

  b=5;

  c=a,b;

  d=(a,b);

 

  printf("c=%d" ,c);

  printf("d=%d" ,d);

 

}

The output for this program is:

(a) c=3 d=3
(b) c=5 d=3
(c) c=3 d=5
(d) c=5 d=5

解释:该题考察逗号运算符和逗号表达式的相关知识。逗号表达是的求解过程:顺序求解各表达式,整个逗号表达式的值是最后一个表达式的值。

7. Consider the following program:

main()

{

  int a[][3] = { 1,2,3 ,4,5,6};

  int (*ptr)[3] =a; //定义一个指向一个三元整型数组的指针,并将数组a的地址赋给它

 

  printf("%d %d "  ,(*ptr)[1], (*ptr)[2] );

 

  ++ptr;//此处自增1,实际为ptr+sizeof(int *[3]),即此时ptr指向4.

  printf("%d %d"  ,(*ptr)[1], (*ptr)[2] );

}

The output for this program is:

(a) 2 3 5 6
(b) 2 3 4 5
(c) 4 5 0 0
(d) None of the above

解释:该题考察的是指针和数组相关知识点。

8. Consider following function

int *f1(void)

{

  int x =10;

  return(&x); //

}

 

int *f2(void)

{

  int*ptr;

  *ptr =10;

  return ptr;

}

 

int *f3(void)

{

  int *ptr;

  ptr=(int*) malloc(sizeof(int));

  return ptr;

}

Which of the above three functions are likely to cause problem with pointers

(a) Only f3
(b) Only f1 and f3
(c) Only f1 and f2
(d) f1 , f2 ,f3

解答:f1返回指针指向一个栈中的局部变量,该变量在函数返回后销毁,所以返回的指针非法;f2中所定义的指针指向一个常数错误,在初始化时没有给一个有效的地址;f3正确。

9. Consider the following program:

main()

{

  int i=3;

  int j;

 

  j = sizeof(++i+ ++i);

 

  printf("i=%d j=%d", i ,j);

}

The output for this program is:

(a) i=4 j=2
(b) i=3 j=2
(c) i=3 j=4
(d) i=3 j=6

解答:sizeof不会对表达式求值,所以j = sizeof(++i + ++i)不会修改i的值。

10. Consider the following program:

void f1(int *, int);

void f2(int *, int);

void(*p[2]) ( int *, int);

 

main()

{

  int a;

  int b;

 

  p[0] = f1;

  p[1] = f2;

  a=3;

  b=5;

 

  p[0](&a , b);

  printf("%d/t %d/t" , a ,b);

 

  p[1](&a , b);

  printf("%d/t %d/t" , a ,b);

}

 

void f1( int* p , int q)

{

  int tmp;

  tmp =*p;

  *p = q;

  q= tmp;

}

 

void f2( int* p , int q)

{

  int tmp;

  tmp =*p;

  *p = q;

  q= tmp;

} 

The output for this program is:

(a) 5 5 5 5
(b) 3 5 3 5
(c) 5 3 5 3
(d) 3 3 3 3

解答:该题考察了函数指针和函数参数传递知识点。由于C语言的参数传递都是值传递的过程,所以在f1f2函数中不能实现交换两个数的功能,只是将前一个数赋值给了另一个数

11. Consider the following program:

void e(int );  

 

main()

{

  int a;

  a=3;

  e(a);

}

 

void e(int n)

{

  if(n>0)

  {

    e(--n);

    printf("%d" , n);

    e(--n);

  }

}

The output for this program is:

(a) 0 1 2 0
(b) 0 1 2 1
(c) 1 2 0 1
(d) 0 2 1 1

解答:该题是考察函数递归调用和变量的作用范围,注意不同函数里面的n值。

12. Consider following declaration

typedef int (*test) ( float * , float*)

test tmp;

type of tmp is

(a) Pointer to function of having two arguments that is pointer to float
(b) int
(c) Pointer to function having two argument that is pointer to float and return int
(d) None of the above

解答:该题是考察对typedef的理解。

13. Consider the following program:

main()

{

  char *p;

  char buf[10] ={ 1,2,3,4,5,6,9,8};

  p = (buf+1)[5];

  printf("%d" , p);

}

The output for this program is:

(a) 5
(b) 6
(c) 9
(d) None of the above

解答:该题考察的是数组和指针的相关知识。关于数组和指针有几条规则:规则1.表达式中的数组名(与声明不同)被编译器当作一个指向该数组第一元素的指针;规则2.下标总是与指针的偏移量相同;规则3.在函数参数的声明中,数组名被编译器当作指向该数组第一个元素的指针。注意在一下情况下应该将数组作为一个整体来考虑:数组作为sizeof()的操作数——显然此时需要的是整个数组的大小,而不是指针所指向的第一个元素的大小;使用&操作符取数组的地址;数组是一个字符串(或宽字符串)常量初始值。

14. Consider the following program:

Void f(char**);

 

main()

{

  char * argv[] = { "ab" ,"cd" , "ef" ,"gh", "ij" ,"kl" };

  f( argv );

}

 

void f( char **p )

{

  char* t;

 

  t= (p+= sizeof(int))[-1];

 

  printf( "%s" , t);

}

The output for this program is:

(a) ab
(b) cd
(c) ef
(d) gh

解答:该题仍然是考察数组和指针的相关知识点。由于sizeof(int)=4,所以p+=4p所指向的是”ij”字符串,再t= (p+= sizeof(int))[-1]后此时t所指向的是p前一个字符串即”gh”.

15. Consider the following program:

#include<stdarg.h>

int ripple ( int , ...);

 

main()

{

  int num;

  num = ripple ( 3, 5,7);

  printf( " %d" , num);

}

 

int ripple (int n, ...)

{

  int i , j;

  int k; 

  va_list p;

 

  k= 0;

  j = 1;

  va_start( p , n);    

 

  for (; j<n;  ++j)

  {

    i =  va_arg( p , int);

    for (; i;    i &=i-1  )//完成的功能相当求数中1得个数

      ++k;

  }

  va_end( p);

  return k;

}

The output for this program is:

(a) 7
(b) 6
(c) 5
(d) 3

解答:该题考察C语言中参数可变函数的相关知识。

16. Consider the following program:

int counter (int i)

{

  static int count =0;

  count = count +i;

  return (count );

}

main()

{

  int i , j;

 

  for (i=0; i <=5; i++)

    j = counter(i);

}

The value of j at the end of the execution of the this program is:

(a) 10
(b) 15
(c) 6
(d) 7

 

 解答:该题考察static关键字的相关知识点。Static声明的局部变量应该注意一下几点:1,变量所在的存储区在静态存储区内分配单元,在整个程序运行期间都不释放;2,对静态局部变量是在编译时赋初值的,即只赋初始值一次,在程序运行时它已有初值,以后每次调用函数时不再重新赋值而是只保留上次函数调用结束时的值;3,如果在定义时不赋初值时,则编译时期自动赋初始值为0(对整型变量)或空字符(对字符变量);4,虽然静态局部变量在函数调用结束后仍然存在,但是其它函数是不能引用它的。

 

 

 

 

 

 

 

 

 

 

 

 

 原文地址 http://www.programmersheaven.com/articles/pathak/article2.htm
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值