C语言经典笔面试题—下
- 1、已知一个数组table,用一个宏定义,求出数据的元素个数。
- 2、对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++ 中应用什么实现?
- 3、用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
- 4、以下为Linux下的32位C程序,请计算sizeof的值。
- 5、请写出bool flag与“零值”比较的if语句
- 6、请写出int变量n、float x与“零值”比较的if语句
- 7、请写出char *p与“零值”比较的if语句
- 8、以下是求一个数的平方的程序,请找出错误
- 9、有符号数转无符号数
- 10、怎么判断单向链表中是否有环?
- 11、下面的代码输出是什么,为什么?
- 12、switch()的参数类型可以是实型吗?
- 13、头文件包含
- 14、头文件中的ifndef/define/endif 干什么用?
- 15、嵌入式系统经常要求程序员去访问某特定的内存位置。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。
- 16、要对绝对地址0x100000赋值,我们可以用*(unsigned int*)0x100000 = 1234;那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做
- 17、在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”
- 18、一语句实现x是否为2的若干次幂的判断
- 19、C语言中的整数自动转换问题
- 20、C语言中处理器字长问题
1、已知一个数组table,用一个宏定义,求出数据的元素个数。
#define NTBL(table) (sizeof(table)/sizeof(table[0]))
2、对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++ 中应用什么实现?
c用宏定义,c++ 用inline函数
3、用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
注意末尾的UL。
4、以下为Linux下的32位C程序,请计算sizeof的值。
char str[] = “Hello” ;
char *p = str ;
int n = 10;
void Func ( char str[100])
{
}
void * p = malloc( 100 );
请计算
(1)sizeof (str ) =
(2)sizeof ( p ) =
(3)sizeof ( n ) =
(4)sizeof( str ) =
(5)sizeof ( p ) =
答案:
(1)6、(2)4 、(3 )4 (4)4 (5)4
关于C语言中char、short、int、long在不同系统中各占多少字节,可以参考:结构体的对齐规则及举例
5、请写出bool flag与“零值”比较的if语句
if ( flag ) if ( !flag )
6、请写出int变量n、float x与“零值”比较的if语句
int
if ( n == 0 ) if ( n != 0 )
float:不可将浮点型变量用“==”或“!=”与数字比较,应该设法转化为“>=”或“<=”此类形式。
const float EPSINON = 0.00001;
if((x >= - EPSINON)&&(x <= EPSINON)
7、请写出char *p与“零值”比较的if语句
if (p == NULL) if (p != NULL)
8、以下是求一个数的平方的程序,请找出错误
#define SQUARE(a) ((a)*(a))
int a = 5;
int b;
b = SQUARE(a++);
宏在预编译时会以直接替换的形式展开。涉及到宏的地方,谨慎使用++、- - ,该程序的结果不确定,依赖于不同编译器,可能为25,也可能为30。
9、有符号数转无符号数
#define Max_CB 500
void LmiQueryCSmd(StructMSgCB * pmsg)
{
unsigned char ucCmdNum;
......
for(ucCmdNum=0;ucCmdNum< Max_CB;ucCmdNum++)
{
......;
}
}
这段代码执行有什么问题?
死循环。
unsigned char //无符号字符型表示范围0~255
char // 有符号字符型 表示范围-128~127
10、怎么判断单向链表中是否有环?
答:用两个指针来遍历这个单向链表,第一个指针p1,每次走一步;第二个指针p2,每次走两步;当p2 指针追上p1的时候,就表明链表当中有环路了。
int testLinkRing(Link *head)
{
Link *t1=head,*t2=head;
while( t1->next && t2->next)
{
t1 = t1->next;
if (NULL == (t2 = t2->next->next))
return 0; // 无环
if (t1 == t2)
return 1;
}
return 0;
}
11、下面的代码输出是什么,为什么?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b> 6)? puts("> 6") : puts("<= 6");
}
这个问题测试你是否懂得C语言中的整数自动转换原则,
当表达式中存在有符号类型和无符号类型时,所有的数都自动转换为无符号类型。因此-20 变成了一个非常大的正整数,所以该表达式计算出的结果大于6 。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。
12、switch()的参数类型可以是实型吗?
不可以。
13、头文件包含
#include <filename.h> 和#include “filename.h” 有什么区别?
对于#include <filename.h> ,编译器从标准库路径开始搜索filename.h ;
对于#include “filename.h” ,编译器从用户的工作路径开始搜索filename.h 。
14、头文件中的ifndef/define/endif 干什么用?
防止该头文件被重复引用。
15、嵌入式系统经常要求程序员去访问某特定的内存位置。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。
int * ptr;
ptr= (int *)0x67a9;
*ptr = 0xaa66;
16、要对绝对地址0x100000赋值,我们可以用*(unsigned int*)0x100000 = 1234;那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做
*((void (*)( ))0x100000 ) ( );
首先要将0x100000强制转换成函数指针,即:
(void (*)())0x100000
然后再调用它:
*((void (*)())0x100000)();
用typedef可以看得更直观些:
typedef void(*)() voidFuncPtr;
*((voidFuncPtr)0x100000)();
17、在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”
首先,extern是C/C++语言中表明函数和全局变量作用范围的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。
通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。extern "C"是连接申明(linkage declaration),被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。
作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与c语言的不同。例如,假设某个函数的原型为:void foo( int x, int y );该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。
所以,可以用一句话概括extern “C”这个声明的真实目的:解决名字匹配问题,实现C++与C的混合编程。
18、一语句实现x是否为2的若干次幂的判断
a如果是2的若干次幂,那么它的二进制就只有一个1,转换成二进制就能看出来了
int main(void)
{
int a;
scanf("%d",&a);
printf("%c",(a)&(a-1)?'n':'y');//若是打印y,否则n
}
或直接
return !(x&(x-1));
注意&为位与,&&为逻辑与
19、C语言中的整数自动转换问题
下面的代码输出是什么,为什么
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}
这个问题测试你是否懂得C语言中的整数自动转换原则,该无符号整型问题的答案是输出是 “>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。
因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是非常重要的。
20、C语言中处理器字长问题
评价下面代码片段:
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */
对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:
unsigned int compzero= ~0;
这一问题真正能揭露出应试者是否懂得处理器字长的重要性。