1.下面函数传入9999,返回什么
int func(int x)
{
int countx = 0;
while (x)
{
countx++;
x = x&(x - 1);
}
return countx;
}
思路:将x转化为2进制,看含有的1的个数。答案是8.。
2.请说出const与#define相比,有何优点
const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应) 。
有些集成化的调试工具可以对 const 常量进行调试,但是不能对宏常量进行调试。
3.a[]数组a和&a的区别
void main()
{
int a[5] = {1,2,3,4,5};
int *ptra = (int *)(a + 1);
int *ptrb=(int *)(&a+1);
cout << *(a + 1) << " " << *(ptra- 1)<<" "<<*(ptrb-1) << endl;//输出2 1 5
}
4.typedef和define的区别
用法不同:typedef用来定义一种数据类型的别名,增强程序的可读性。define主要用来定义常量,以及书写复杂使用频繁的宏。
5.常函数
常量类型的函数只有权读取外部数据内容,但无权修改他们。
格式
<类型说明符><函数名>(<参数表>)const;
当一个函数被const说明后,其函数中出现的对外部数据的任何写入或修改都将被系统检查为出错。如果把函数writeme()说明为:
void writeme(int i) const { me = i; }
系统将会检查出错误。
作用
当函数体较大且复杂时,如果我们希望系统帮助避免对对象内容进行修改,那么我们就会将这个函数定义为常量型函数,这就是使用它的主要目的。
6.SendMessage和PostMessage的区别
- 返回值不同
LRESULT SendMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);返回消息处理的结果
BOOL PostMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);返回BOOL表示加入消息队列是否成功 - PostMessage 是异步的,SendMessage 是同步的。
PostMessage 只把消息放入队列,不管消息是否被处理就返回,消息可能不被处理;而 SendMessage 等待消息被处理完了之后才返回,如果消息不被处理,发送消息的线程将一直被阻塞。 - 如果在同一个线程内,SendMessage 发送消息时,由 USER32.DLL 模块调用目标窗口的消息处理程序,并将结果返回。SendMessage 在同一线程中发送消息并不入线程消息队列。PostMessage 发送消息时,消息要先放入线程的消息队列,然后通过消息循环分派到目标窗口(DispatchMessage)。
如果在不同线程内,SendMessage 发送消息到目标窗口所属线程的消息队列,然后发送消息的线程在 USER32.DLL 模块内监视和等待消息处理,直到目标窗口处理完返回。
Post 到别的线程时,最好用 PostThreadMessage 代替 PostMessage,PostMessage 的 hWnd 参数可以是 NULL,等效于 PostThreadMessage + GetCurrentThreadId。Post WM_QUIT 时,应使用 PostQuitMessage 代替。 - A线程向B线程SendMessage,C再向A线程SendMessage,A可以处理C的SendMessage吗?答案是可以。
如果在不同线程内,SendMessage 发送消息到目标窗口所属线程的消息队列,然后发送消息的线程在 USER32.DLL 模块内监视和等待消息处理,直到目标窗口处理完返回。SendMessage 在返回前还做了很多工作,比如,响应别的线程向它 SendMessage。
7.STL具体实现
map的实现
STL中map的实现是基于RBTree。
vector的实现
Vector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存。
8.全局变量和静态变量的区别
- static全局变量与普通的全局变量有什么区别 ?
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。
全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。
这两者的区别在于非静态全局变量的作用域是整个源程序,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。
静态全局变量是显式用static修饰的全局变量,作用域是声明此变量所在的文件,其他的文件即使用extern声明也不能使用。 - static函数与普通函数有什么区别?
static函数与普通函数作用域不同,仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static修饰的函数),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件。
static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。
全局变量、静态全局变量、静态局部变量和普通局部变量的区别
9.数组和链表的区别
从逻辑结构上来说,这两种数据结构都属于线性表
- 数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素(随机访问)。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。
- 链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素(顺序访问),需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。
10.临界区,互斥量,信号量和事件之间的区别
11.空类占内存吗
空类增加一个一字节的哑成员来占位。C++中规定无数据成员的结构有最小的非零长度,为了防止与他相邻的数据对象有相同的地址。
12.智能指针
13.说说你对封装,继承的理解,多态。
14.什么是预编译?何时需要预编译?
主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作。预编译又称为预处理 , 是做些代码文本的替换工作。
15.字符常量和数组的存储
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";
cout << (str1 == str2) << endl;//0
cout << (str3 == str4) << endl;//0
cout << (str5 == str6) << endl;//1
cout << (str7 == str8) << endl;//1
str1,str2,str3,str4是数组变量,他们有各自的内存空间;而str5,str6,str7,str8是指针,他们指向相同的常量区域。
16.sizeof()的问题
#include<iostream>
using namespace std;
void fun(char str[])
{
cout << sizeof(str) << endl;//4
}
int main()
{
char str[] = "aBcDe";
cout << sizeof(str) << endl;//6
fun(str);
cout << str << endl;//aBcDe
return 0;
}
sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组的大学。函数外的str是一个静态定义的数组,因此其大小为6,因为还有‘\0’,函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。
17.越界访问
int main()
{
char a;
char *str = &a;
strcpy(str, "hello");
printf(str);
return 0;
}
没有为str分配内存空间,将会发生异常。问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。
18.修改字符常量的值
char *s = "AAAA";
printf("%s", s);
s[0] = 'B';
printf("%s", s);
对是s[0]的赋值操作是不合法的,修改字符常量的值是不合法的。
19.嵌入式系统中经常需要用到无限循环
``cpp
while(1)
{
}
```cpp
for(;;)
20.volatile
当要求使用volatile声明变量值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。精确地说就是,遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问;如果不使用valatile,则编译器将对所声明的语句进行优化。
1>告诉compiler不能做任何优化。
2>用volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能重复使用放在cache或寄存器中的备份。
21.进程之间通信的途径
答:共享存储系统、消息传递系统、管道:以文件系统为基础
22.进程死锁的原因和4个必要条件
答:资源竞争及进程推进顺序非法;互斥、请求保持、不可剥夺、环路
23.死锁的处理
答:鸵鸟策略、预防策略、避免策略、检测与解除死锁
24. 操作系统中进程调度策略有哪几种?
答:FCFS(先来先服务),优先级,时间片轮转,多级反馈
25.ISO的七层模型是什么?tcp/udp是属于哪一层?tcp/udp有何优缺点?
答:应用层、表示层、会话层、运输层、网络层、物理链路层、物理层 tcp/udp属于运输层
TCP服务提供了数据流传输、可靠性、有效流控制、全双工操作和多路复用技术等。 与TCP 不同, UDP并不提供对IP协议的可靠机制、流控制以及错误恢复功能等。由于UDP比较简单,UDP头包含很少的字节,比TCP负载消耗少
tcp: 提供稳定的传输服务,有流量控制,缺点是包头大,冗余性不好 udp: 不提供稳定的服务,包头小,开销小
26.变量转换
unsigned short A = 10;
printf("~A=%u\n", ~A);//~A=4294967285
char c = 128;
printf("c=%d\n", c);//c=-128
第一题,~A =0xfffffff5, int值为-11,但输出的是uint。所以输出4294967285。
第二题,char是有符号的,c=0x80,输出的是int,最高位为1,是负数,所以它的值就是0x00的补码就是128,所以输出-128。
27.对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?
答:c用宏定义,c++用inline
28.内存对齐
typedef union { long i;int k[5];char c; }DATE;
struct data { int cat;DATE cow;double dog; }too;
DATE max;
printf("%d\n", sizeof(too) + sizeof(max));//20+32=52
29.100位两个非负大数相乘
#include<stdio.h>
#include<string.h>
#define INT(x) (x-'0')
#define CH(x) (x+'0')
char A[101];
char B[101];
char result[200];
int main()
{
while (scanf("%s %s",A,B)==2)
{
int sizeA = strlen(A);
int sizeB = strlen(B);
memset(result, 0, sizeof(result));
for (int i = 0;i < sizeB;i++)
{
int rest = 0;
for (int j = 0;j < sizeA;j++)
{
result[199 - i - j] += INT(B[sizeB - 1 - i])*INT(A[sizeA - 1 - j]) + rest;
rest = result[199 - i - j] / 10;
result[199 - i - j] = result[199 - i - j] % 10;
}
result[199 - i - sizeA] += rest;
}
int n = 0;
while (n < 200 && result[n] == 0)
{
n++;
}
if (n == 200)
{
printf("0\n");
}
else
{
for (int i = n;i < 200;i++)
{
printf("%c", CH(result[i]));
}
printf("\n");
}
}
return 0;
}