转载的mtk笔试

写在今天:

不怨天不怨地了,没有什么伤不起。

那些心酸,那些泪,那些悲欢聚散,好的坏的我全收起。

纠缠久了,会烦,会痛,会厌,会累,会神伤,会心碎。

依旧放不下,但要自信地微笑,再自信地做好该做的事。

勇敢一点,没什么大不了。

// 开始找工作的生活了,每一次笔试,机试,面试都不要小瞧,弄懂见过的每一道题

这是今天MTK笔试中,我遇到的一些不确定的题目,我尽力大致做了解答


http://topic.csdn.net/u/20110915/11/dbc28cd0-abf5-463b-8e34-b8ef59e9aaf6.html

好久没来,给大家也做做贡献


给定一个整数N,求N!中有几个0,编程实现

不是太难吧!哈哈



选择题

1. unsigned long u11 = 0x00001111;

unsigned long u12 = 0x00000202;

unsigned long u1 = u11 & (~u12);

u1 = u1 | u12;

结果:u1 = 0x00001313

2. 一个线性栈,进站顺序s1,s2,s3,s4,s5,s6,s7;出栈顺序s2,s1,s3,s5,s7,s6,s4, 栈的深度至少是(3)

解析:1进,2 进,2出,1出

3进,3出

4进,5进,5出

6进,7进,7,6,4出

3. Ripple 什么什么的。Va_list不懂。。。

va_list的解释:http://intijk.com/?p=174 看完这个博客就懂了。。。

以下几个宏:

  • va_list
  • va_start
  • va_arg
  • va_end

va_list 用来定义一个变量列表的指针类型.
va_start(listPointer, n) 的意思是将 listPointer 这个指针绑定到有 n 个变量的传入参数列表上.
va_arg(listPointer, type) 从参数列表中逐个取出数据, 取出数据的类型由 type 决定, 它返回这个 type 类型的值, 你可以马上把它赋值给另一个变量.
当函数调用结束的时候, 要记得使用 va_end 来清除 listPointer 指向的空间, 否则会发生内存泄漏问题.

 

4. Static 类型在memory中位于()——堆栈,RO,RW,ZI 不懂,不会啊。。。

一个ARM程序包含3部分:RO,RW和ZI

RO是程序中的指令和常量
RW是程序中的已初始化变量
ZI是程序中的未初始化的变量

 

问答题

Typedef 和define

typedef是一种在计算机编程语言中用来声明自定义数据类型,配合各种原有数据类型来达到简化编程的目的的类型定义关键字。 #define是预处理指令。下面让我们一起来看。

typedef是C语言语句,其功能是用户为已有数据类型取“别名”。

例如:

typedef int INTEGER;

这以后就可用INTEGER来代替int作整型变量的类型说明了,如:

INTEGER a,b;

用typedef定义数组、指针、结构等类型将带来很大的方便,不仅使程序书写简单而且使意义更为明确,因而增强了可读性。例如:

typedef int a[10];//表示a是整型数组类型,数组长度为10。

然后就可用a说明变量,如:

a s1,s2;//完全等效于:int s1[10],s2[10] ; 同理 typedef void (*p)(void) 表示p是一种指向void型的指针类型!

#define是预处理中的宏定义命令,例如:

#define int PARA

表示在源程序中的所在int将会被PARA原样代替!

如:程序中有int a,b ;则在编译前将被替换为PAPA a,b;

#define是C中定义的语法,typedef是C++中定义的语法,二者在C++中可以通用,但#define成了预编译指令,typedef当成语句处理。Typedef和define都可以用来给对象取一个别名,但是两者却有着很大不同。

1. 首先,二者执行时间不同

关键字typedef在编译阶段有效,由于是在编译阶段,因此typedef有类型检查的功能。

Define则是宏定义,发生在预处理阶段,也就是编译之前,它只进行简单而机械的字符串替换,而不进行任何检查。

#define用法例子:

#define f(x) x*x main( ) { int a=6,b=2,c; c=f(a) / f(b); printf("%d \n",c); } 程序的输出结果是: 36,根本原因就在于#define只是简单的字符串替换,应当加个括号“(X*X)”。

2. 功能不同

Typedef用来定义类型的别名,这些类型不只包含内部类型(int,char等),还包括自定义类型(如struct),可以起到使类型易于记忆的功能。

如:

typedef int (*PF) (const char *, const char *); 定义一个指向函数的指针的数据类型PF,其中函数返回值为int,参数为const char *。

typedef 有另外一个重要的用途,那就是定义机器无关的类型,例如,你可以定义一个叫 REAL 的浮点类型,在目标机器上它可以i获得最高的精度:

typedef long double REAL; 在不支持 long double 的机器上,该 typedef 看起来会是下面这样:

typedef double REAL; 并且,在连 double 都不支持的机器上,该 typedef 看起来会是这样:

typedef float REAL;

#define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。

3. 作用域不同

#define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用。而typedef有自己的作用域。

void fun() { #define A int } void gun() { //在这里也可以使用A,因为宏替换没有作用域, //但如果上面用的是typedef,那这里就不能用A ,不过一般不在函数内使用typedef }

4. 对指针的操作

二者修饰指针类型时,作用不同。

Typedef int * pint; #define PINT int * Const pint p;//p不可更改,p指向的内容可以更改,相当于 int * const p;

Const PINT p;//p可以更改,p指向的内容不能更改,相当于 const int *p;或 int const *p; pint s1, s2; //s1和s2都是int型指针

PINT s3, s4; //相当于int * s3,s4;只有一个是指针。

其实,typedef和define末尾的标号也是不一样的,希望大家不要忽略这一点。

 

Extern C

extern "C"包含双重含义,其一:被它修饰的目标是“extern”的;其二:被它修饰的目标是“C”的。

1)被extern “C”限定的函数或变量是extern类型的;

extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其他模块中使用。

注意:extern int a;

仅仅是在声明一个变量,并不是定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。

通常,在模块的头文件中对模块提供给其他模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错,它会在连接阶段中从模块A编译生成的目标代码中找到此函数。

与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern "C"修饰。

2)被extern "C"修饰的变量和函数是按照C语言方式编译和连接的

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:void foo(int x, int y);

该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能产生的名字不同,但是都采用了相同的机制)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo(int x, int y)与void foo(int x, float y)编译产生的符号是不相同的,后者为_foo_int_float。

 

Const的含义

单链表相交,如何求交点

先看下链表环路的问题:

有一个单向链表,如何判定这个链表当中是否包含有环路,以及如何定位环路在链表当中的开始点呢?

关于第一个问题,网络上可以搜索到,用两个指针来遍历这个单向链表,第一个指针p1,每次走一步;第二个指针p2,每次走两步; 当p2 指针追上 p1的时候,就表明链表当中有环路了。

关于这个解法最形象的比喻就是在操场当中跑步,速度快的会把速度慢的扣圈

可以证明,p2追赶上p1的时候,p1一定还没有走完一遍环路,p2也不会跨越p1多圈才追上

我们可以从p2和p1的位置差距来证明,p2一定会赶上p1但是不会跳过p1的

因为p2每次走2步,而p1走一步,所以他们之间的差距是一步一步的缩小,4,3,2,1,0 到0的时候就重合了

根据这个方式,可以证明,p2每次走三步以上,并不总能加快检测的速度,反而有可能判别不出有环

比如,在环的周长L是偶数的时候,初始p2和p1相差奇数的时候,p2每次走三步,就永远和p1不重合,因为他们之间的差距是: 5, 3 , 1, L-1, L-3

关于第二个问题,如何找到环路的入口,是这里要重点说明的内容:

解法如下: 当p2按照每次2步,p1每次一步的方式走,发现p2和p1重合,确定了单向链表有环路了

接下来,让p2回到链表的头部,重新走,每次步长不是走2了,而是走1,那么当p1和p2再次相遇的时候,就是环路的入口了。

这点可以证明的:

在p2和p1第一次相遇的时候,假定p1走了n步骤,环路的入口是在p步的时候经过的,那么有

p1走的路径: p+c = n; c为p1和p2相交点,距离环路入口的距离

p2走的路径: p+c+k*L = 2*N; L为环路的周长,k是整数

显然,如果从p+c点开始,p1再走n步骤的话,还可以回到p+c这个点

同时p2从头开始走的话,经过n不,也会达到p+c这点

显然在这个步骤当中p1和p2只有前p步骤走的路径不同,所以当p1和p2再次重合的时候,必然是在链表的环路入口点上

接下来回归原题目:

首先应该分两种情况考虑,第一:这两个链表本身都没有环。 第二:这两个链表本身都有环
首先讲都没有环的情况,

1) 遍历第一个链表 求长度M

2) 遍历第二个链表 求长度N

3) 选择M和N中较大的那个

4) 将较长的链表遍历至第M-N个节点

5) 然后在两个链表中同步遍历,比较next指针是否相等且不为NULL。

6) 如果相等,则next指针所指的元素即为交点。

7) 如果为NULL,说明两个链表都到了末端还没有相交

然后说第二种情况

两个链表本身都有环,首先我们应该知道如果一个链表有环


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值