设为首页 加入收藏

TOP

C语言学习趣事_经典面试题系列_3 (一)
2014-11-23 22:30:31 来源: 作者: 【 】 浏览:4
Tags:语言学习 趣事 经典 试题 系列

有日子没有学习C语言了, 前些天在看windows程序设计时, 按照win的体系结构,在VC 6里面找到

下面一段代码,发现自己的C语言功底实在是差之又差。代码为我看到的C代码,至目前为止,还只能理解个大概;

估计要慢慢体会了。

View Code
DECLARE_HANDLE(HDC);#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
上面的代码等我理解后再和大家分享吧, 下面说说这一次的C语言面试题。

8、找错题
找出下面几个函数的错误:
试题1:
void test1()
{
 char string[10];
  char* str1 = "0123456789";
  strcpy( string, str1 );
}

/*
这个题目咋一看,没有任何错误, 给strcpy()函数传递的两个实参参数类型均能满足要求。
但是细心一看我们会发现这个函数存在越界问题,"0123456789"这个字符串
的长度为 strlen("0123456789") + 1 = 11 , 而很显然string[10],不可能存储这么大的空间
通常在使用strcpy函数时一定要考虑源串、和目的串的大小问题。

*/
函数改成下面的形式可能会健壮一些:
int StrCpy(const char *source; char dest[])
{
if( NULL==source || NULL == dest || ( strlen(dest) < strlen(source) ) )
return 1; // 返回值=1 表示复制失败
else
strcpy(dest,source);
return 0; //返回值=0 表示复制成功
}

试题2::
void test2()
{
  char string[10], str1[10];
  int i;
  for(i=0; i<10; i++)
  {
   str1 = 'a';
  }
 strcpy( string, str1 );
}
/*
这个题目考查了两个问题:
1、 数组的首地址是常量,不可以作为左值, 即str1是一个常量,
它代表整个数组的首地址。
2、 第二数组的引用需要用下标,除了初始化时可以int iArray[10]={1,2}
这样赋值外,在其他地方不可以批量给数组元素赋值。
3、 同时strcpy复制函数是针对具有'\0'的字符类型变量,因此这个函数赋
值同样存在赋值越界的情况。
*/
改成下面的方式估计会健壮一些:
void test2( )
{
  char string[10],
str1[10] ;
  for(int i=0; i<10; i++)
   str1[i] = 'a';
str[9]='\0';
  strcpy(string , str1);
}

试题3:
void test3(char* str1)
{
  char string[10];
  if( strlen( str1 ) <= 10 )
  {
   strcpy( string, str1 );
  }
}
//试题3同样存在越界的可能性。如果strlen(str1)=10, 则实际上str1占用的空间是11个。
//strlen函数返回的长度没有计算末尾'\0'字符。 因此需要注意。
改为下面的方式可能会更健壮:
void test3(char* str1)
{
  char string[10];
  if( strlen( str1 ) < 10 && NULL != str1 )
   strcpy( string, str1 );
}


试题4:
void GetMemory( char *p )
{
  p = (char *) malloc( 100 );
}

void Test( void )
{
  char *str = NULL;
  GetMemory( str );
  strcpy( str, "hello world" );
  printf( str );
}
/*
首先这个题目存在内存泄露的问题和指针指向空地址问题
说说这个题目的存在的几个问题:
1、 在GetMemory函数里面, 没有对malloc函数返回值进行测试
if(NULL==p)
2、 在函数里面没有对指针p进行释放
free(p);
3、这里会有一个问题,在C语言中默认时按值传递的, 不是按照地址传递的。
在程序里面不能改变str的指向。
GetMemory(str);不能改变str的指向。
函数原型为:
void GetMemory(char *p); 定义的就是一个指针类型的参数。
4、在函数内部不能改变传值参数的值
*/

/*****************
malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,
它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求
的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果
有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多
的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,
malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大
的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要
进行返回值的判断。
**************/

改成下面形式可能更健壮一些:
Void GetMemory(char **p)
{
char *temp;
if(NULL != (temp=(char *)malloc(1000)))
*p=temp;
free(temp);
}

试题5:
char *GetMemory( void )
{
 char p[] = "hello world";
 return p;
}

void Test( void )
{
 char *str = NULL;
 str = GetMemory();
 printf( str );
}

/* 其实怎么说呢这个题目的理解比上面一个题目来对简单, 但是通过这个题目和上面
的题目需要知道一个事实:
那就是函数内部声明的局部变量(static类型的除外,当然还有register的除外),这里指的
是auto类型的变量, 其内存空间是在系统为应用程序开辟的栈里面申请。
而malloc函数申请的空间则是从系统为应用程序开辟的堆里面申请。堆里面申请的不会自动释放,
而栈里面申请的会随着函数声明周期的结束而自动释放。
这个题目的错误之处在于没有理解局部变量的生命周期。
*/
改成下面的形式可能会更

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇HDU 1102 Constructing Roads 下一篇c语言Problem 1_03_guess

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: