经典C语言能力测试题(值得一看)

2024-06-06 18:32

本文主要是介绍经典C语言能力测试题(值得一看),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

绝对能够测试你的C语言功力的几个问题!
很少有真正精通了C语言编程的学员,一般都有或多或少概念不是完全清楚的问题,特别是一些需要丰富的实战经验才能体会和明白的问题,如字符串,指针,类型转换,定义指向函数的指针类型,这也是导致学习C困难的一个原因。下面有几个简单测试将能发现你对C语言的掌握情况。
1)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,但是数组外部的数据已经被破坏
strlen的值为13,在VC++环境下,x的值是要改变的(其他编译器下没试,).虽然表面上看来,在程序中并没有修改x的值,但是实际运行的结果是上面的x的值发生了修改,这是因为strcpy以后,把多余的数据拷贝进了str的邻居(int类型的x)中,所以x的数据也就变了.这是一个曾让我刻骨铭心的问题,在我刚出道时遇到这个问题,虽然在朋友的帮助下解决了这个问题,但一直不明白x的值为何变了,只有最后走上培训教师的岗位,才开始梳理自己曾经的困惑,才开始总结以前的经验供学员们借鉴.我觉得这个题目的价值非常之大,它能引起学员对字符串拷贝越界问题的足够重视,并且通过这个问题更能明白字符串的处理是怎么回时,更能明白字符串与字符数组的关系:字符串就是一个字符数组,只是把这个字符数组用在处理串的函数中时,这些函数不考虑数组的长度,只是记住数组的首地址,从首地址开始处理,并在遇到0时结束处理,

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

4)char *pstr;
strcpy(pstr,"http://www.it315.org");
//上句编译能通过吗?运行时有问题吗?
答:可以通过编译,但是pstr指向了常量区,运行时最好只做读操作,写操作不保险。
编译可以通过,但是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*
注意:非const指针不能指向const区域,会引起错误。


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;
补充::函数指针最大的用处在于它可以被一个模板方法调用,这是我在学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函数就可以了.

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

这篇关于经典C语言能力测试题(值得一看)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1036893

相关文章

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

Go语言使用Gin处理路由参数和查询参数

《Go语言使用Gin处理路由参数和查询参数》在WebAPI开发中,处理路由参数(PathParameter)和查询参数(QueryParameter)是非常常见的需求,下面我们就来看看Go语言... 目录一、路由参数 vs 查询参数二、Gin 获取路由参数和查询参数三、示例代码四、运行与测试1. 测试编程路

Go语言使用net/http构建一个RESTful API的示例代码

《Go语言使用net/http构建一个RESTfulAPI的示例代码》Go的标准库net/http提供了构建Web服务所需的强大功能,虽然众多第三方框架(如Gin、Echo)已经封装了很多功能,但... 目录引言一、什么是 RESTful API?二、实战目标:用户信息管理 API三、代码实现1. 用户数据

Go语言网络故障诊断与调试技巧

《Go语言网络故障诊断与调试技巧》在分布式系统和微服务架构的浪潮中,网络编程成为系统性能和可靠性的核心支柱,从高并发的API服务到实时通信应用,网络的稳定性直接影响用户体验,本文面向熟悉Go基本语法和... 目录1. 引言2. Go 语言网络编程的优势与特色2.1 简洁高效的标准库2.2 强大的并发模型2.

Go语言使用sync.Mutex实现资源加锁

《Go语言使用sync.Mutex实现资源加锁》数据共享是一把双刃剑,Go语言为我们提供了sync.Mutex,一种最基础也是最常用的加锁方式,用于保证在任意时刻只有一个goroutine能访问共享... 目录一、什么是 Mutex二、为什么需要加锁三、实战案例:并发安全的计数器1. 未加锁示例(存在竞态)

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1

Go语言使用select监听多个channel的示例详解

《Go语言使用select监听多个channel的示例详解》本文将聚焦Go并发中的一个强力工具,select,这篇文章将通过实际案例学习如何优雅地监听多个Channel,实现多任务处理、超时控制和非阻... 目录一、前言:为什么要使用select二、实战目标三、案例代码:监听两个任务结果和超时四、运行示例五

C语言中%zu的用法解读

《C语言中%zu的用法解读》size_t是无符号整数类型,用于表示对象大小或内存操作结果,%zu是C99标准中专为size_t设计的printf占位符,避免因类型不匹配导致错误,使用%u或%d可能引发... 目录size_t 类型与 %zu 占位符%zu 的用途替代占位符的风险兼容性说明其他相关占位符验证示