ZZ测试你的C语言功底?


摘自:http://www.51asm.com/Aboutlesson.aspx(科锐软件教育首页)




在实际的教学中,我们发现很少有真正精通了C语言编程的学员,一般都有或多或少概念不是完全清楚的问题,特别是一些需要丰富的实战经验才能体会和明白的问题,如字符串,指针,类型转换,定义指向函数的指针类型,这也是导致学习VC++困难的一个原因。下面有几个简单测试将能发现你对C语言的掌握情况。
 
1、如何在下面的test函数里加入代码可以使程序运行起来输入和输出的相等?
  

(环境是vc6Debug方式下)
#include<stdio.h>
void test()
{
  int t;
  scanf("%d",&t);
  在这里加入代码
 }
main()
{
  int m;
  test();
  printf("m=%d",m);
}

  

  
 
2、请运行下面的代码,观察结果,有人说怎么是死循环,你同意吗?为什么?
  

#include <stdio.h>
int main()
{
  int i = 0;
  int name[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

  for (i = 0; i <= 10; i++)
  {
    name[i] = 0;
    printf("ok/n");
  }
  return 0;
}


  
 
3、实现多参函数
  

  大家对C语言中最熟悉的函数就是“printf”吧?这是在HelloWorld例子里就见过了。那么你真正了解它吗?请设计一个类似于printf的函数的多参函数int Add(…);
这个函数的功能:
例如Add(4, 5, 0); 返回9
Add(4, 5, 6, 0);返回15…………可以输入大于0个参数(参数类型为整型)。


 
参考答案
一、

这一题需要去了解在函数体中栈内存的分配情况。
#include<stdio.h>
void test()
{
//
当程序流程进入test函数入口的时候也会对变量作一些寄存器的保护和预留空间
//  push  ebp
//  mov  ebp,esp
//  sub  esp,48h
//  push  ebx
//  push  esi
//  push  edi
//  lea  edi,[ebp-48h]
//  mov  ecx,12h
//  mov  eax,0CCCCCCCCh
//  rep stos  dword ptr [edi]
//  
预留了0x12*sizeof(DWORD)个字节空间
//  
变量t的地址为ebp-4
  int t;
  scanf("%d",&t);//?
请在以下添加代码,使用main函数中的变量m输出值等test函数中的变量t;
//
计算变量t在内存中的位置和上一层函数中变量m在内存中位置的差
//
先写到这一句用反汇编看一下
//
变量tm都在预留空间的最下端(堆栈是向上长的,变量是按定义先后也是从下向上放的)
//push  edi(main)...............................0x1
//push  esi(main)...............................0x2
//push  ebx(main)...............................0x3
//push  ebp(
自己)...............................0x4
//
返回地址............................................0x5
//0x10*sizeof(DWORD)
的空间............................0x15
//
空间最下面的DWORD字节存放变量m......................0x16
//
我们把t向下偏移0x16的位置(存放着变量m)上把t的内容写进去即可。
//
也可以看一下OD里图:

qwe

  *( &t + 0x16) = t;
//
这样整型指针pos就指到了变量m我们把t的值直接赋给*p(就是m)即可。
}
int main()
{
//
当程序进入main函数的时候,会对一些局部变量作一些预留空间
//  push  ebp
//  mov  ebp,esp
//  sub  esp,44h
//  push  ebx
//  push  esi
//  push  edi
//  lea  edi,[ebp-44h]
//  mov  ecx,11h
//  mov  eax,0CCCCCCCCh
//  rep stos  dword ptr [edi]
//  
预留了0x11*sizeof(DWORD)个字节空间
//  m
的变量地址是ebp-4

  int m;
  test();
  printf("m=%d",m);
  return 0;
}



二、

我们一起来看一下此程序的反汇编:

aa

在系统的实现中,i和数组name[10]是分配在栈上的变量,在内存中的分布如下图:

name[0]

name[1]

name[2]

name[3]

name[4]

name[5]

name[6]

name[7]

name[8]

name[9]

i(name[10])

从上图和表中可以看出i所占据的正是name[10]的位置,而name[10] = 0;这一句会被这样运行:
*(name + 10) = 0;
所以这一句的结果,就是把0赋值给i。这样一来在第11次循环的时候,i将会被重新置为0,那么循环结束的条件也就永远不会满足了,循环也就是个死循环了。

三、
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值