常见面试题及其解答--问题摘自程序员面试笔试宝典(未完待续)

(1)extern的作用。

这个应该分为才C和C++中的区别。C语言中extern声明的函数和变量可以被该文件外部的模块引用,C++中除了该作用以外,还可以声明extern “C”用来表示一段代码编译连接的方法为C语言的方法。

1.extern是C/C++语言中声明函数和全局变量作用范围的关键字,改关键字告诉编译器,其声明的函数和变量在本模块或其他模块中使用,通常,在模块的头文件中,对本模块提供给其他模块引用的函数和全局变量以关键字extern声明。

2.被extern “C”修饰的变量和函数是按照C语言的方式编译连接的,由于C++支持重载,所以其函数编译的方式与C语言的编译方式不同,这一句的作用就是实现C++和C及其他语言的混合编程。

(2)strstr函数的作用。

strstr()函数的原型一般为extern char *strstr(const char *src,const char *dest),其作用就是寻找目标子串在源字符串中第一次出现的位置,strstr是针对char型数组的,如果是string类型的字符串,相应的find函数也可以完成这一功能

(3)windows线程优先级问题

每个线程都会被赋予一个从0(最低)到31(最高)的优先级号码。当系统确定将哪个线程分配给CPU的时候,它首先观察优先级为31的线程,并以循环的方式对他们进行系统的调用,如果优先级为31的线程可以调度,那么就赋予该线程一个CPU时间片,在该线程的时间片结束的时候,系统要查看是否 还有另一个优先级为31的线程可以运行,如果有,它将允许该线程被赋予CPU时间片。

只要有优先级为31的线程是可以调度的,系统就绝对不会将优先级为0到30的线程分配给CPU,这种情况称为渴求调度,这里存在一个问题,是否低优先级的线程永远得不到调用,因为在任何一个时间段内,系统中的大多数线程是不能调用的,例如:如果主线程调用GetMessage函数,而系统发现没有线程可供使用,那么系统就暂停进程的线程运行,释放该线程的剩余时间片,并立即将CPU分配给另一个等待运行的线程,高优先级的线程会抢占低优先级的线程。

当系统引导的时候,它会常见一个特殊的线程,称为0线程,该线程被赋予优先级0,它是整个系统中为一的一个在优先级0上运行的线程,当系统中没有任何线程需要执行的时候,0线程负责将系统中所有的空闲的RAM页面置为0。

相比于这个问题,进程和线程的区别可能更为常见。

通常一个进程可以包含若干个线程,他们可以利用进程所拥有的资源,进程是系统进行资源分配和调度的一个独立单位,线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本不拥有系统资源,只拥有一些在运行中必不可少的资源(如程序计数器,一组寄存器和栈),线程可与同属于一个进程的其他线程共享进程所拥有的全部资源。

线程和进行的区别课归纳为:

地址空间和其他资源:进程间这些资源是互相独立的,而同一个进程的各个线程共享这些资源。

通信:进程间通信是利用IPC,线程间可以直接读写进程数据的来进行通信(需要进行同步和互斥的辅助)

调度和切换:线程上下文切换比进程上下文切换快速、高效。

多线程的OS中,进程不是一个可执行的实体。

(4)多方法交换x与y的值。

这里给出一种方法。

x = x ^ y;

y = x ^ y;

x = x ^ y;

利用异或实现两个数值的交换。

(5)指针的自加与引用。

指针的自加

例如 :

int a = 3;

int *p = a; 

p++;

自加过后p指向a后面的内存了,而不是对a的数值进行++操作。((*p)++可以实现对a的自加操作)

指针的引用

指针的引用(*&),相当于是指针的指针,这样指针的数值是可以改变的

其次谈一谈指针与引用。而单传递指针,那么指针指向的数据是可变的,指针自身是不可变的,

简单归纳,即:*&指针本身可变,*指针本身不可变,仅指向的内容可变。

相同点:

都是地址概念。指针指向一块内存,它的内容是所指内存的地质,引用是某块内存的别名。

区别:

1、引用带定义的时候必须进行初始化,并且后面不能改变其引用,指针不必

2、指针可以为空,引用不能为空

(6)前置++与后置++

前置是先自加,在使用,后置是先使用,在自加。

关于这两个,有一点需要区别的应该是重载的时候,后置++有一个int型的参数。

(7)inline的作用

inline函数不像正常函数在调用时存在压栈和call的操作,它会把代码直接嵌入到调用代码段中,也就是说,使用inline函数会增加二进制程序的体积,但是会使执行速度加快,同时,编译期间可以对参数进行强类型的检查,这是inline优于define的一个方面。

(8)二维数组的表示

这个···a[][] 或者 vector< vector<type> >  

(9)ifndef的作用

条件编译的语法,一般情况下,源程序中的所有行都参与编译,但是有时希望对其中一部分内容旨在满足一定的条件时在进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。有时,希望当满足某条件时,对一组语句进行编译,二当条件不满足时,编译另一组语句。

(10)KMP算法

KMP算法是字符匹配算法,详见KMP字符匹配

(11)函数调用方式

调用函数时,计算机常用栈来存储要传递给函数的参数,在参数传递的过程中,有两个问题需要明确说明

1.当参数个数多于一个时,按什么顺序吧参数压入堆栈。

2.函数调用后,由谁来把堆栈恢复原状。

常用的函数调用方式:stdcall,cdecl,fastcall,thiscall

stdcall:参数从右向左依次压入堆栈,由被调函数自己来恢复堆栈,

cdecl:参数从右向左依次压入堆栈,由调用者恢复堆栈。

fastcall:函数的第一个和第二个参数通过exc和edx传递,后面的参数从右向左依次压入堆栈,由调用函数清理堆栈。

thiscall:参数从右向左依次压入堆栈,由调用者清理堆栈。

(12)重载函数

重载函数是指,在同一作用域内,可以有一组或多组,具有相同函数名,不同参数列表的函数,这些同名函数称为重载函数。(仅仅是返回类型不同不构成重载,而会有重定义的错误)。类中的const函数和非const函数可以重载,其原理救赎利用this指针的类型分别是const和非const的进行重载,即参数类型不同构成重载。

(类的成员函数后面加const,表明这个函数不糊对这个类的对象的数据成员作任何改变)

(13)构造函数与析构函数

(14)合并两个有序链表

(15)100亿条记录的文本文件,取出重复数最多的前10条。

考虑到100亿条数据量太大,分成多组,然后分别建立哈希表,找出各组的重复数最多的10条,,然后把这多组合并再求其重复数最多的十条。

(16)设计一个双向链表,并提供一个可根据值删除元素的函数。

(17)二叉树的多种遍历算法的实现。

前序中序后续,递归循环,这里还提出一个Morris遍历,大家有兴趣可以去了解一下。

(18)有读和写两个线程和一个队列,读线程从队列中读数据,写线程,往队列中写数据。

生产者和消费者模型:

    使用信号灯和互斥量。

semaphore mutex = 1;
semaphore fillCount = 0;
semaphore emptyCount = BUFFER_SIZE;
 
procedure producer() {
    while(true) {
        item = produceItem();
        down(emptyCount);
            down(mutex);
                putItemIntoBuffer(item);
            up(mutex);
        up(fillCount);
    }
}
procedure consumer() {
    while(true) {
        down(fillCount);
            down(mutex);
                item = removeItemFromBuffer();
            up(mutex);
        up(emptyCount);
        consumeItem(item);
    }
}
不使用信号的和互斥量:

volatile unsigned int produceCount, consumeCount;
TokenType buffer[BUFFER_SIZE];
  
void producer(void) {
    while (1) {
        while (produceCount - consumeCount == BUFFER_SIZE)
            sched_yield(); // 缓冲区满
  
        buffer[produceCount % BUFFER_SIZE] = produceToken();
        produceCount += 1;
    }
}
  
void consumer(void) {
    while (1) {
        while (produceCount - consumeCount == 0)
           sched_yield(); // 缓冲区空
  
        consumeToken( buffer[consumeCount % BUFFER_SIZE]);
        consumeCount += 1;
    }
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值