Chinaunix首页 | 论坛 | 博客
  • 博客访问: 157621
  • 博文数量: 50
  • 博客积分: 83
  • 博客等级: 民兵
  • 技术积分: 297
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-12 11:47
文章分类
文章存档

2012年(43)

2011年(7)

分类:

2011-10-30 21:08:16

 
 
另外,在实际的VC++教学中,发现很少有真正精通了C语言编程的学员,一般都有或多 或少概念不是完全清楚的问题,特别是一些需要丰富的实战经验才能体会和明白的问题,如字符串,指针,类型转换,定义指向函数的指针类型,这也是导致学习 VC++困难的一个原因。下面有几个简单测试将能发现你对C语言的掌握情况。
排了一下题号,重发

// test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
/* 第 1 题 */
int x=35;
char str[10];
//问:strlen(str)和sizeof(str)的值分别是多少?


/* 第 2 题 */
strcpy(str,""/*共13个字母*/);
//问:此时x和strlen(str)的值分别是多少?


/* 第 3 题 */
str="it315.org";//编译能通过吗?
//error C2440: “=” : 无法从“const char [10]”转换为“char [10]”


/* 第 4 题 */
char *pstr;
strcpy(pstr,"http://");
//上句编译能通过吗?运行时有问题吗?


/* 第 5 题 */
const char *p1;
char * const p2;
//上面两句有什么区别吗?
//error C2734: “p2” : 如果不是外部的,则必须初始化常数对象


/* 第 6 题 */
p1=(const char *)str;
//如果是p1=str;编译能够通过吗?明白为什么要类型转换?类型转换的本质是什么?


/* 第 7 题 */
strcpy(p1,"abc");//编译能够通过吗?
//error C2664: “strcpy” : 不能将参数 1 从“const char *”转换为“char *”


/* 第 8 题 */
printf("%d",str);//有问题吗?


/* 第 9 题 */
pstr=3000;//编译能过吗?如果不行,该如何修改以保证编译通过呢?
//error C2440: “=” : 无法从“int”转换为“char *”


/* 第 10 题 */
long y=(long)pstr;//可以这样做吗?
// warning C4311: “类型转换” : 从“char *”到“long”的指针截断


/* 第 11 题 */
int *p=str;
//error C2440: “初始化” : 无法从“char [10]”转换为“int *”


/* 第 12 题 */
*p=0x00313200;
printf("%s",str);//会是什么效果?提示0x31对应字符'1',0x32对应字符'2'。


/* 第 13 题 */
p=3000;//p+1的结果会是多少?
//error C2440: “=” : 无法从“int”转换为“int *”



return 0;
}
对于许多类似的问题一般从书本上是看不到的,不通过大量的实践与调试是难以理解和令人困惑的,所以在本书中对于类似上述的C语言问题都将作出详细的解释和讲解。




第一题,sizeof当然是10,strlen就看你运气了,栈上没0的话,可能crash的
第二题,根据我义务教育阶段养成的对错误题目的作者意图猜测能力,这道题目作者其实想考的就是,字符串拷贝越界以后内容会达到x的堆栈位置,其实如果编译器优化了,x很可能就在寄存器里面,所以这个题目是没确定答案的,这个语句最终或许可能导致crash。
第三题,当然不能通过
第四题,能通过,运行的时候还是那句话,凭运气;)
第五题,一个const的是value,一个const的是pointer本身
第六题,能。类型转换的本质,老大你告诉我吧:D
第七题,不能
第八题,没问题,如果这就是你想要的结果的话;)
第九题,不能的,加个explicit cast就可以了
第十题,可以
十一题,输出空白而已,你前后两个0夹着,自然就是空串
十二题,p=3000根本编译不过
十三题,老大你怎样定义内存块?;)
十四题,没问题。char* p; test(&p);就行了
十五题,typedef一个函数指针类型而已

顺便指出一下,这些题目依赖于具体情况不说,单单本身的错误也不少。譬如说,第五题,char * const p2;这样的语句编译是不会通过的;第十一题,int*p=str;这样的语句,不加强制转换也是不可能编译通过的;第十二题也类似。或许是因为张先生平 时都在写那些知识讲解的原创,不是经常写程序,所以对这样的基本错误不很敏感了。当然,出题目总是方便的,只要不给答案就行:)

其实这些东西,正如前面一位兄弟回答的,书上都是有的,只要看对书就行了。而且,不懂这些东西可能说明一个人C语言不好,但是懂了,绝对不能说明他C语言好。

期待看到张先生其它的原创,我发誓我绝对不会盗用的。 






nt x=35;
char str[10];

//问:strlen(str)和sizeof(str)的值分别是多少?
// strlen(str) 值不确定,strlen根据'/0'确定字符串是否结束。
// sizeof(str)=10 sizeof一个数组为数组长度

strcpy(str,""/*共13个字母*/);
//问:此时x和strlen(str)的值分别是多少?
// x 为35
// strcpy(char* dest, const char* src)
// 根据src来复制dest,依照src的'/0'决定复制的长度,而dest必须要提供足够的长度,这里会引起溢出,strlen返回13,但是数组外部的数据已经被破坏

str="it315.org";//编译能通过吗?
// 数组不能赋值,只能初始化。char str[10] = "it315.org";
// 而且初始化时编译器会检查数组的长度与初始化串的长度是否匹配

char *pstr;
strcpy(pstr,"http://");
//上句编译能通过吗?运行时有问题吗?
// 可以通过编译,但是pstr指向了常量区,运行时最好只做读操作,写操作不保险

const char *p1;
char * const p2;
//上面两句有什么区别吗?
// const char* 和 char const* 一样,都是表示指向常量的字符指针。
// char * const 表示指向字符的常量指针

p1=(const char *)str;
//如果是p1=str;编译能够通过吗?明白为什么要类型转换?类型转换的本质是什么?
// 可以通过编译。关于常量与非常量指针的关系是这样的:
// const指针可以指向const或者非const区域,不会造成什么问题。
// 非const指针不能指向const区域,会引起错误。

strcpy(p1,"abc");//编译能够通过吗?
// 不能通过,strcpy( char*, const char*); char* 不能指向const char*

printf("%d",str);//有问题吗?
// 没有问题,输出的是str的地址信息。

pstr=3000;//编译能过吗?如果不行,该如何修改以保证编译通过呢?
// 不能通过,char* pstr表示pstr是个字符指针,不能指向3000的整形变量。
// 修改的话,可以这样:pstr = (char*)3000,把pstr指向3000这个地址;

long y=(long)pstr;//可以这样做吗?
// 可以,y的值为pstr所指的地址。不过如果是纯粹要地址的话,最好是用unsigned long。

int *p=str;
*p=0x00313200;
printf("%s",str);//会是什么效果?提示0x31对应字符'1',0x32对应字符'2'。
// 首先编译未必会过关,有些编译器可能不允许int * 直接指向char*。最好是改为int *p = (int*)str;
// 过关了效果就是什么东西都没有。int *p=str; p为str所指的地址,*p表示修改了str所指向的内存。
// 由于sizeof(int)在32位机上,int有4个字节(其实具体要看编译器的配置文件,好像是limit.h,一般是4个字节)所以修改了str[0]-str[3]
// 由于0x00313200头尾都是0,所以字符串为'/0'开头,什么都打印不出来。这里有个Big-endin和little-endin的问题。以0x31323334为例
// little-endin的机器上面,0x31323334在内存中排列顺序为34 33 32 31,输出为4321,如INTEL芯片的pc
// big-endin机器上面为31 32 33 34 ,输出为1234,如IBM POWERPC

p=3000;//p+1的结果会是多少?
// 3000+sizeof(int); 指针+1均为原来地址加上sizeof(指针所指的数据类型)

char *pc=new char[100];//上述语句在内存中占据几个内存块,怎样的布局情况?
// 本身pc会占用函数栈一个4字节的指针长度(具体是否为4个字节要看机器和编译器)。
// new会在堆上申请100个字节sizeof(char)的连续空间。

void test(char **p)
{
*p=new char[100];
}//这个编译函数有问题吗?外面要调用这个函数,该怎样传递参数?
// 该程序没有问题。需要在函数中对指针所指的地址进行变化是必须传人指针的地址。
// 原因是这样的:如果传入的为指针本身,在函数调用的时候,实参会被复制一个实例,这样就不是原来的指针了,对该指针本身进行的任何改变都不能传递回去了。
// 可以这样理解,如果传入的参数为int,那么对int本身的值的改变就传不回去啦,加个*也是一样的。


//能明白typedef int (*PFUN)(int x,int y)及其作用吗?
// 定义了一个函数指针类型的宏,这样PFUN就表示指向返回值为int,且同时带2个int参数的函数指针类型了。
// 可以用来定义这样的变量:
// 比如有个函数为int fun( int x, int y );
// PFUN p = fun;


下面是网友Jackie214发布的答案,其认真态度令我深受感 动.这些题是我2000年在做培训时为学员们设计的,但我已经近6年没有接触过vc++下的c语言编程了,有9年没接触unix下的c语言编程了,所以, 除了一些核心思想令我终生难忘外,其他一些语法细节和当初出题的意图何在,我也差不多忘记了!前天把这个测试题发布出来,是因为前一阵才知道我多年前写的 一些内容又要被别人加入到其书籍中出版(我只是对一些人惯于借鉴别人的东西而当作自己成就的性格很不赞赏,但这般行为在商业上来说是无可厚非,甚至是值得 学习,只是我自己做不出这样的事情来,反而有点自己没胆量吃葡萄,
阅读(1318) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~