C语言测试题注意事项

int x=35;
char str[10];

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

strcpy(str,”www.it315.org”/共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://www.it315.org“);
//上句编译能通过吗?运行时有问题吗?
// 可以通过编译,但是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;

下面是我的一点补充:
第二题:
int x=35;
char str[10];
strcpy(str,”www.it315.org”/共13个字母/);
//问:此时x和strlen(str)的值分别是多少?
答:strlen的值为13,在VC++环境下,x的值是要改变的(其他编译器下没试,).虽然表面上看来,在程序中并没有修改x的值,但是实际运行的结果是上面的x的值发生了修改,这是因为strcpy以后,把多余的数据拷贝进了str的邻居(int类型的x)中,所以x的数据也就变了.这是一个曾让我刻骨铭心的问题,在我刚出道时遇到这个问题,虽然在朋友的帮助下解决了这个问题,但一直不明白x的值为何变了,只有最后走上培训教师的岗位,才开始梳理自己曾经的困惑,才开始总结以前的经验供学员们借鉴.我觉得这个题目的价值非常之大,它能引起学员对字符串拷贝越界问题的足够重视,并且通过这个问题更能明白字符串的处理是怎么回时,更能明白字符串与字符数组的关系:字符串就是一个字符数组,只是把这个字符数组用在处理串的函数中时,这些函数不考虑数组的长度,只是记住数组的首地址,从首地址开始处理,并在遇到0时结束处理,
第四题:
char *pstr;
strcpy(pstr,”http://www.it315.org“);
//上句编译能通过吗?运行时有问题吗?
答: 编译可以通过,但是pstr没有进行有效的初始化,它指向了一个不确定的内存区,运行时会出现内存不可写错误!
最后一题:
//能明白typedef int (*PFUN)(int x,int y)及其作用吗?
答:函数指针最大的用处在于它可以被一个模板方法调用,这是我在学java的设计模式时领悟到的.例如,有两个函数的流程结构完全一致,只是内部调用的具体函数不同,如下所示:
void func1()
{
//一段流程代码和面向方面的代理,如安全检查,日志记录等
int sum = add( x , y);
//一段流程代码和面向方面的代理,如安全检查,日志记录等
}
void func2()
{
//与func1完全相同的一段流程代码和面向方面的代理,如安全检查,日志记录等
int difference = sub( x , y);
//与func1完全相同的一段流程代码和面向方面的代理,如安全检查,日志记录等
}
那么,可以只定义一个函数,如下所示
void func(PFUNC p)
{
//与func1完全相同的一段流程代码和面向方面的代理,如安全检查,日志记录等
int difference = p( x , y);
//与func1完全相同的一段流程代码和面向方面的代理,如安全检查,日志记录等
}
调用程序在调用时,让参数p分别指向add和sub函数就可以了.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言编程注意事项 1. 每个程序中一定包含main()函数, 尽管C语言中对函数命名没有限制。 2. printf函数永远不会自动换行, 只能用\n来实现, 回车键进行的换行在编译中会出现错误信息。 3. 在vs2008等平台中编译、测试要加 system("pause"); 来暂停dos自动退出引起的printf无法显示。 4. 所有自定义变量必须声明才能使用。 5. 每行一般只写一条语句, 在运算符两边加一个空格, 便于阅读。 6. 整数除法将会自动舍位, 不进行四舍五入的操作。 7. for(初始化部分;条件部分;增长部分) 比while 更适用于初始化和增长步长都是单条语句的情况。 8. 使用 #define 名字替换文本对部分"幻数" 赋予意义便于阅读 #define结尾无需;号来结束。 9. EOF(end of file)表示没有字符输入时定义在stdio.h 头文件中 EOF不等于\n 换行等。 10. 由于!= 的优先级大于 = ,因此如果对判断中存在变量赋值时 应对赋值加() 例如: while((c = getchar()) != EOF)。 11. getchar() 用于用户输入直至键入回车键。 12. 变量名以字母和数字组成, (下划线"_"被默认为字符, 以下划线为首写字母的为库类变量名), 变量常以小写字母开头,内部变量名前31位有效, 外部变量名至少前6位保持唯一性。 13.在C语言中是区分字母大小写的。 14. 一个字符常量为一个整数, 用''单引号括起来。例如: '0' 为48, 它与0没有任何关系。 15. ANSI C语言的转义符: \a 响铃符; \b 回退符; \f 换页符; \n 换行符; \r 回车符; \t 横向制表符 ; \v 纵向制表符; \\ 反斜杠; \? 问号; \' 单引号; \" 双引号; \ooo 八进制数; \xhh 十六进制数; '\0' 表示0, 即(null)。 16. 'x'与"x"的区别: 'x'表示一个整数, 字母x在其字符集中对应的数值, "x"表示包含一个字符x 以及一个结束符'\0'。 17. const在声明变量中起限制作用, 该限定变量的值不能被修改。 18. %运算符不能应用于float或double类型。 19. char类型转换为int型时, 因为无法判断它是signed还是unsigned,这样其结果有可能为负数, 所以转换时尽量指定signed和unsigned限制符。 20. ++i与i++ 的不同之处: ++i是先 +1再使用i, i++ 是先使用i再 +1。 21. 三元运算符"?:" 第一个表达式的括号不是必须的, 但是由于三元表达式的优先级非常低, 因此我们还是将第一个表达式用()括起来以便于阅读和理解。 22. C语言中可以使用递归 (即函数调用自身函数), 这样做并不节省储存空间也不加快执行速度, 只是使程序紧凑便于理解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值