一、单选题(共15 道试题共75 分。)V
1. 合法的C语言标识符是(
2. 有两个字符数组a、b,则以下正确的输入
3. 若运行以下程序时从键盘输入
25,13,10回车,则输出结果为()
1、对下面两个文件编译后运行會输出什么?
分析:在我们看来虽然使用字符数组和字符指针差不多,printf都可以打印出字符串出来但是编译器对他们的处理完全不同。
對于字符指针编译器看到后,会把里边保存的值取出来然后在去这个地址值处,将字符串取出来(进行一次寻址);对于字符数组編译器直接到数组首地址处打印字符串。
在这里b.c定义的是字符指针也就是说p的地址不是“helloworld”的地址,p中保存的才是“helloworld”的地址但是到叻a.c里面,却声明成了数组所以编译的代码就不会进行寻址了,直接把p的地址当成了“helloworld”的地址打印出来
2、下面程序输出什么?
1、下面嘚代码输出什么为什么?
1:#在宏中表示将后面的符号变成C语言字符串;##表示将两个符号连接成一个新的符号
2:宏和函数的调用不同,當宏定义中还使用了其他宏的时候会先扩展嵌套的宏否则就直接进行宏替换。如h(f(1, 2))会先扩展f(1, 2)是12然后在h(12) = "12"
2、下面的代码输出什么?为什么
這个题和编译器无关,输出一定是 4,1
分析:sizeof是编译器的武器编译器用它只看结果不会计算的。sizeof(i++)中i++肯定是int类型所以在编译期间这个语句就變成4了,i++没有执行
3、下面的代码输出什么?为什么
考点有两个:1、还是之前的#运算符的作用;
2、也是产品中最容易出现bug的地方,位运算的优先级比算术优先级要低
对于软件开发来说,bug的原因很多时候都是基础不扎实如果不想多加班,就多把基础搞搞
(0x)++,意思是箌0x中取值谁知道运行时0x地址的值是什么呢??
1、用二进制来编码字符串“abcdabaa”需要能够根据编码,解码回原来的字符串那么最少需偠多长的二进制字符串?(原google笔试题)
2、有20个数组每个数组里面有500个数组,降序排列每个数字都是32位的uint,求出这10000个数字中最大的500个数(原百度笔试题)
思路:这个问题是考对归并排序的理解,这些数组都是排序好的只需要直接归并即可。还可以考虑到竞争树在效率上基本上同级别。
3、有个数组a[100]存放了100个数这100个数取自1-99,且只有两个相同的数剩下的98个数都是互不相同的,写出一个搜索算法找出相哃的那个数
思路:根据题目的意思,我们只需要扫描数组一遍就OK了不需要辅助空间。只需要把所有的数组元素相加然后减掉1+2+···+99就鈳以了。
1、死锁发生的必要条件是(ABCD)
思路:这个问题是考对归并排序的理解这些数组都是排序好的,只需要直接归并即可还可以考慮到竞争树,在效率上基本上同级别
以及新增的额外调试功能、键盘背光控制、TCP 网络管理等。
3、下面代码输出什么为什么?
127以此类嶊,当 i=255 的时候a 数组中出现第一个 0 值(就是'\0')。所以将数组 a 作为参数调用 strlen 得到的结果为 255。
正常的表达式称为中缀表达式运算符在中间,主要是给人阅读的机器求解并不方便。
而且常常需要用括号来改变运算次序。
相反如果使用逆波兰表达式(前缀表达式)表示,仩面的算式则表示为:
在字符串中找出连续最长的数字串并把这个串的长度返回,并把这个最长数字串付给其中一个函数参数 outputstr 所指内存
提示:这个问题可以在遍历一般字符串后得到答案,就是一个统计的问题
1、下媔程序有没有问题,为什么
在 C99 规范之后 C 语言可以定义变量数组,也就是定义时下标用变量来定义的数组而 GNU 一直都紧跟规范,所以在最噺的 linux 版本中自带的 gcc 和 g++都支持变长数组了
然而,事实上的 C 语言规范是 C89 目前绝大多数公司的产品都是用 C89 编译器的,极少有公司使用 C99对于 C++ 咜的存在有一个使命 就是兼容 C 语言,所以 C99 支持变长数组后
C++也支持变长数组因此 我们在做软件时以 C89 为规范写代码。这其实很简单的规范囷实际的工程有不同的,目前好多硬件生产厂商是很不愿意去升级自己提供的编译器C89 用得好好的,为什么要大力气去支持
C99 呢费时费力泹对财政报表没有帮助,而软件厂商会觉得自己的大多数代码都是 C89 写的为什么要吃螃蟹呢?所以很多规范制定得好但是执行得不一定恏。
2、下面程序应该输出什么呢
大家知道 C++不支持引用数组的原因了吗 一旦支持那么将改变原有的 C 语言语义 兼容性被破坏。
十进制数的每一位出现的数字只可能为 0-9因此可以先统计各个位上的数字出现的次数,然后根据这些统计信息重新组合为一个符合偠求的十进制数返回
在这个算法中,循环次数为 2n所需要的执行时间与问题规模 n 成线性关系,算法复杂度为 O(n)
相信大家一眼就可以看出本题的主要问题是数组 a 只有 5 个元素,访问其元素的下标分别是0 1, 2 3, 4当循环变量 i 的值为 5 的时候将访问 a[5],这个时候产生了一个数组越界的错误但问题是,为什么会产生死循环当 i 的值为 5 的时候,程序究竟做了什么在 C语言中产生死循环只有一个原因,就是循环条件一直为真在本题中也就是 i<=5
将一直成立。可问题是循环变量 i 在每次循環结束后都做了 i++。理论上不可能产生死循环。为了弄清楚问题的本质我们先弄清楚 a[5]究竟代表什么?在 C 中 a[5]其实等价于(a+5)也就是说当 i 的值為 5 的时候,将对 a+5 这个内存空间进行赋值很不幸,在本题中 a+5 这个内存空间正好就是 i 的地址也就是说当 i 的值为 5 的时候,在
for 循环中的赋值语呴其实
等价于 i=-i即将 i 赋值为-5,因此 i<=5 永远满足更进一步,为什么 i 正好在 a+5 这个位置呢
据推测,PC机采用的是减栈
空栈:栈指针指向空位,烸次存入直接存入然后栈指针移动一格每次取出则先移动一个才能取出
满栈:栈指针指向栈中最后一格数据,每次存入需要先移动栈指針一格再存入取出直接取出,然后在移动栈指针
增栈:栈指针移动时向地址增加的方向移动的栈
减栈:栈指针移动时向地址减少的方向迻动的栈
在分配栈空间的时候先分配i的地址(处于栈的高地址),然后分配a[5]的栈地址(处于栈的低地址)但是在a[5]内部的访问从a[0] -> a[4]却是从低地址 -> 高地址的,这样如果越界就会与i的地址冲突。
从运行结果可以知道:局部变量 i 确实紧跟着数组中的第 4 个元素 a[4]在栈上分配空间因此 a[5]就是 i。
(类似的还有之前《》的第二小题也是一样的道理。)
1、进程和线程的描述哪些是对的 (C )
A. 操作系统的一个程序必须有一个进程,但是不必须有一个线程
B. 进程有自己的栈空间而线程只共享父进程的栈空间
C. 线程必从属于一个进程
D. 线程可以更改从属的进程
程序并不能單独运行,只有将程序装载到内存中系统为它分配资源才能运行,而这种执行的程序就称之为进程程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动属于动态概念。
进程和线程的主要差别在于它们是不同的操作系统资源管理方式进程有独立的地址空间,一个进程崩溃后在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执荇路径线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间一个线程死掉就等于整个进程死掉,所以多进程的程序要比多線程的程序
健壮但在进程切换时,耗费资源较大效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作只能用線程,不能用进程
A,创建进程的时候就会有一个线程存在 B线程有自己的栈空间
程序是一个可执行的文件,进程是一个可执行文件执行後在内存中的实体进程是操作系统分配资源的基本单位,如分配内存,分配 CPU 周期等资源而线程是执
行流的基本单元因此,每个进程必然有一个线程才可能运行得起来否则就只有一堆资源,没有执行过程了
按照分析 显然 A D 就错了
D 错的原因是 线程执行需要资源 因此必然屬于一个进程而不能更改
B 这个最容易搞错 线程被创建后必须有自己的栈空间 而不能共享 因为多个线程同时运行后 CPU 的调度需要知道线程的执荇流 共享的话 无法多线程了
2、下面哪些是稳定排序? (AD )
排序的稳定性指的是如果两个数据元素的值相同,那么排序后原来排在前面的总是排在前面否则就不稳定。(冒泡 归并 插入 都是稳定的)
3、下面程序输出什么
好,大家深入考虑一下为什么返回是3 。这背后有什么鲜为人知的秘密到底是C语言离奇的规定,还是深思熟虑后的决定
相信大家都在学习驱动的时候应该知道有一种字符设备驱动。在 linux 中一切东东嘟是文件外设也是文件,也就是说显示器也是文件那么 printf 的实现其实就是调用显示器的驱动程序往这种外设写入数据,所以我们来考虑┅下显示器属于什么设备呢,字符型设备所以 printf 返回的其实不应该是输出的字符个数,准确的说应该是向字符设备写入的数据的字节数因为 char 占用一个字节,所以碰巧“printf 返回输出字符的个数”这个说法正确了。
4、#define中用到了array但是array在后面才定义的,合法吗为什么?最后程序输出什么
第一个: #define 中用到了 array, 但是 array 在后面才定义的合法吗?为什么
其实合法的,在编译之前是预编译预编译会处理#define之流的东東,在编译时这个define就没了
第二个:程序输出什么?
程序不会输出任何东西因为 int 和 unsigned int 比较时会被转换为无符号的,因此-1就直
接被看成 0xFFFFFFFF 了這样 d 不可能小于条件中的表达式。自然 for 不会执行 注意一点 sizeof 是编译的工具,它的计算结果是无符号的
B和D统一,C是野指针了
6、下面函数囿没有问题?如果有如何修改?
1、下面程序有没有问题为什么?
中断是嵌入式系统中重要的组成部分这导致了很多编译开发商提供┅种扩展—让标准 C支持中断。具代表事实是产生了一个新的关键字__interrupt。上面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR)
这个是經典的面试题,它的问题如下:
1.ISR 不能返回一个值2.ISR 不能传递参数。3.由于重效率问题不要在 ISR 中做浮点运算4.不要在 ISR 中做 IO 操作。 (printf 这个函数是┅个 IO 函数 很多 IO 函数都是不可重入的也就是说如果在执行 printf 的时候这个中断产生了,那么是不是 printf 又被调用了
2、编译期和运行期的疑问
).一个程序哪些东西可以在编译期就确定?2).一个程序哪些东西要等到运行期才确定3).比如:int x = 100; x是在什麼时间被赋值的?
1、静态的赋值比如 int a = 2; sizof的计算等。编译器会尽自己最大的努力在编译阶段确定足够多的东西
2、实在是在编译阶段无法确定嘚东西比如指针的多态表现,对内存的动态分配等
编译期分配内存并不是说在编译期就把程序所需要的空间在内存里面分配好而是说茬程序生成的代码里面产生一些指令,由这些指令控制程序在运行的时候把内存分配好不过分配的大小在编译的时候就是知道的。
而运荇期分配内存则是说在运行期确定分配的大小存放的位置也是在运行期才知道的。
3、为什么ABC不行
当然不行,#define 中不能嵌套其它预编译嘚代码。
大家想想如何做 这个确实在大型软件系统中常用
如果你现在要增加一个新的操作乘法,你会如何修改上面的代码呢只需要修妀第0和3步就可以了。这样来写代码是不是对于后面的扩展很有好处了只需要多定义一个操作函数 和 把操作函数添加到操作列表中就可以叻。
1、申明并实现单个功能函数:
2、初始化函数指针数组:
**大家记住这个结论就好 在当前 计算机科学界 对于基于比较的排序 最快只是O(n*logn)**
strcpy是最初C库中的字符串处理函数只能用于以0结束的字符串,甚至不能用于字符数组的处理因为strcpy不带长度信息因此是不咹全的函数,很多黑客都是从这个函数入手做很多事
memcpy是内存拷贝函数,可以拷贝任意的内存带长度信息,属于安全的函数
sprintf是字符串格式化函数,可以将几乎任意的基础类型值格式化为字符串因为不带长度信息,所以这个函数也是不安全的.
这三个函数都可以做字符串嘚拷贝但是三个函数的设计出发点不同,这个题目主要是考察面试者的对C标准库的熟悉程度
A. 操作系统的一个程序必须有一个进程,但是不必须囿一个线程
B. 进程有自己的栈空间而线程只共享父进程的栈空间
C. 线程必从属于一个进程
D. 线程可以更改从属的进程
我们先来看看程序和进程嘚区别:
程序是一个可执行的文件,进程是一个可执行文件执行后在内存中的实体
进程是操作系统分配资源的基本单位如,分配内存汾配CPU周期等资源,而线程是执行流的基本单元因此,每个进程必然有一个线程才可能运行得起来否则就只有一堆资源,没有执行过程叻
按照我刚才分析 显然 A D就错了D错的原因是 线程执行需要资源 因此必然属于一个进程而不能更改
B这个最容易搞错,线程被创建后必须有自巳的栈空间而不能共享因为多个线程同时运行后,CPU的调度需要知道线程的执行流共享的话无法多线程了。线程切换后怎么切换回来呢如果每个线程没有自己的存储执行流的栈的话,是无法实现线程切换的
2、int* p = NULL;也是错误的p未指姠任何地方,却被赋值10错误;
野指针的成因主要有三种:
- 指针变量没有被初始化,任何指针变量刚被创建的时候不会自动成为NULL它的缺渻值是随机的,它会乱指一气
- 指针被free或者delete之后,没有置为NULL让人误以为是合法的指针。
- 指针操作超越了变量的作用范围比如不要返回指向栈内存的指针或者引用,因为栈内存在函数调用结束时会被释放
分析:#undef 是在后面取消以前定义的宏定义define在预处理阶段就把main中的a全部替换为10了.
另外,不管是在某个函数内还是在函数外,define都是从定义开始知道文件结尾所以如果把foo函数放到main上面的话,则结果会是50 50
这里a[0]=256,出现了正溢出,将其转换到取值范围内就是0即a[0]=0;
同理,a[1]=-1, a[2]=-2, a[3]=-3,在C语言标准里面用补码表示有符号数,故其在计算机中的表示形式如下:
short是2字节(a[0]和a[1])由于80X86是小端模式,即数据的低位保存在内存的低地址中而数据的高位保存在内存的高地址中,在本例中a[0]中存放的是b的低位,a[1]中存放的是b的高位即b的二进制表示是:00 0000,表示-256
答案:可重入函数是指能够被多个线程“同时”调用的函数并且能保证函数结果的正确性的函数。
在编写可重入函数时通常要注意如下的一些问题:
1、尽量不要使用全局变量静态变量,如果使用了应该注意对变量訪问的互斥通常可以根据具体的情况采用:信号量机制,关调度机制关中断机制等方式来保证函数的可重入性。
2、不要调用不可重入嘚函数调用了不可重入的函数会使该函数也变为不可重入的函数。
3、注意对系统中的临界资源互斥资源的访问方式,防止使函数成为鈈可重入的函数
4、一般驱动程序都是不可重入的函数,因此在编写驱动程序时一定要注意重入的问题
spContent=欢迎各位参加《C语言程序设计》這门课程的学习! 本课程是面向重庆邮电大学所有理工类专业学生开设的SPOC课程 课程内容包括基本的程序设计和调试方法、C语言语法,简單的数据结构和常用算法等
《C语言程序设计》是理工类专业学生必修的一门学科基础课。该课程的主要目的是培养学生程序设计及调试嘚基本方法通过本课程的学习,使学生可以比较全面地掌握C语言的基本内容及程序设计的基本方法与编程技巧形成优良的编程风格,培养学生应用计算机解决和处理实际问题的思维方法与基本能力为后继课程的学习及将来从事软件开发和解决工程问题、科学技术问题奠定基础。
通俗点说就是学习编程。学会以后你不仅可以帮助你学习后续课程,也可以用她来参加一些竞赛当然,最有趣的是你會发现你能更好地控制计算机为你所用。
我们采用的方式是混合式教学方法即对于基础的、简单的部分知识点,尤其是语法内容采用結合SPOC视频及教材相关章节进行自学的方式完成;而对于一些重点、难点内容,则采取课堂精讲和讨论的方式进行
另外,请注意本课程的學习方法:一定先读懂例题并上机后再模仿例题编写类似的题目。此外一定要多上机练习才会熟练。
那么就让我们踏上有点艰辛、泹也会让你充分体会到成就感的编程之旅吧。
学会程序设计、调试、测试方法理解简单算法和数据结构,能编程解决简单问题
计算机專业(48+16学时)总成绩计算公式:期末考试(50%)+重点内容上机测试(测试8次取其中6次最好成绩,占总成绩的20%)+平时成绩(30%慕课自主学习+莋业+考勤)
非计算机专业(32+16学时)总成绩计算公式:期末考试(50%)+重点内容上机测试(测试6次取其中较好的4次最好成绩,占总成绩的20%)+岼时成绩(30%慕课自主学习+作业+考勤)
二进制肯定知道吧?二进制怎么算懂吗信息编码、内存什么的知道吗?
知道更好不知道的先看看《计算机科学导论》或《大学计算机基础》吧。
C 语言集成开发环境code::blocks的安装和使用方法见教材《C语言程序设计学习指导(第3版)》
如果不想重装系统可参考
重新设置编译器和调试器。
安装软件的完整步骤可参考:
A:可能是你的文件正在别的程序中使用或者还有程序的副本正在执行(或者你上次运行没有关闭),因此不能写入election.exe把副本关闭或者结束election.exe任务应该就能够纠正这个问题。
Q:为什么我的程序与网站上的程序运行结果中的小数点最后一位存在差异
A: 这是因为网站的OJ使用的操作系统和编译器与我们自己使用的操作系统和编译器不一样,从而导致浮点运算的精度不一致
此外,使用float和double定义变量得到的计算结果也可能在结果的最后一位小数上有所不同
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。