C语⾔⾯试基本点整理
⼀、
⼆、
1、static和extern:
1). 在函数体,⼀个被声明为静态的变量在这⼀函数被调⽤过程中维持其值不变。
2). ⼀个被声明为静态的变量可以被模块内所⽤函数访问,但不能被其他⽂件函数访问。它是⼀个本地的全局变量。
3). 在模块内,⼀个被声明为静态的函数只可被这⼀模块内的其它函数调⽤,这个函数被限制在声明它的模块的本地范围内使⽤。
C++中的static
在C++中static还具有其它功能,如果在C++中对类中的某个函数⽤static进⾏修饰,则表⽰该函数属于⼀个类⽽不是属于此类的任何特定对象;如果对类中的某个变量进⾏static修饰,表⽰该变量为类以及其所有
的对象所有。它们在存储空间中都只存在⼀个副本。可以通过类和对象去调⽤。对于静态成员函数,只能访问静态成员函数和静态成员变量,不能访问⾮静态成员函数或者变量。
extern:引⽤其他⽂件的函数或变量
2、内存泄漏:
申请内存后要删除,new和delete的使⽤
确保您不是在访问空指针
malloc和free⼀起使⽤
fwrite和write区别:
fwrite带缓冲,write不带缓冲。⼀个8k的⽂件,指定缓存⼤⼩为2k,则需要4次系统调⽤,fwrite⾃动分配缓冲,⼀次调⽤。
操作系统会定期地把这些存在内核缓冲区的数据写回磁盘中。⽽fwrite不⼀样,fwrite每次都会先把数据写⼊⼀个应⽤进程缓冲区,等到该缓冲区满了,系统会调⽤write⼀次性把相应数据写进内核缓冲区中减少了系统调⽤(即write调⽤)。
C语⾔编译过程:
C语⾔编译过程分成四个步骤:
1,由.c⽂件到.i⽂件,这个过程叫预处理
2,由.i⽂件到.s⽂件,这个过程叫编译
3,由.s⽂件到.o⽂件,这个过程叫汇编
4,由.o⽂件到可执⾏⽂件,这个过程叫链接
宏的本质:预处理阶段的单纯的字符串替换
预处理阶段,不考虑C语法
3、线程和进程:
(1)进程是资源的分配和调度的⼀个独⽴单元,⽽线程是CPU调度的基本单元
(2)同⼀个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下⽂),⼀个进⾏⾄少包括⼀个线程。
(3)进程的创建调⽤fork或者vfork,⽽线程的创建调⽤pthread_create,进程结束后它拥有的所有线程都将销毁,⽽线程的结束不会影响同个进程中的其他线程的结束
(4)线程是轻两级的进程,它的创建和销毁所需要的时间⽐进程⼩很多,所有操作系统中的执⾏功能都是创建线程去完成的
(5)线程中执⾏时⼀般都要进⾏同步和互斥,因为他们共享同⼀进程的所有资源
线程、进程间通信:
进程线程间通信:
1、共享内存
2、信号量:不具备数据传输的功能,只是⼀种外部资源的标识。当请求⼀个使⽤信号量的资源时,进程需要先读取信号量的值,当信号量⼤于0时,表⽰有资源可以请求。当进程不再使⽤⼀个信号量控制的共享资源时,此信号量值加⼀。
3、消息队列:是⼀个消息的链接表
4、读写锁:多个读线程可以共同占有⼀把读写锁,写线程任意时刻只能有⼀个占有读写锁
5、互斥锁:每次只有⼀个线程可以得到锁进⾏操作,其余的线程都因为得不到锁⽽处于阻塞状态。
sizeof是求数据类型所占的空间⼤⼩,⽽strlen是求字符串的长度,字符串以/0结尾。
内存分配⽅式:
静态存储区:全局变量(不在main函数内)和static变量
堆:动态分配内存,除了malloc,其他都不在堆上被创建
栈:局部变量,函数参数;char *p;
4、const、typedef和define区别
typedef:声明新的类型名来代替原有的类型名;⽐如typedef int INTERGER,相当于⽤INTERGER代表int类型。Typedef 在C语⾔中频繁⽤以声明⼀个已经存在的数据类型的同义字
define只是简单的字符串替换,没有类型检查。⽽const有对应的数据类型,是要进⾏判断的,可以避免⼀些低级的错误。
const 定义的常数是变量 也带类型, #define 定义的只是个常数 不带类型。
define是在编译的预处理阶段起作⽤,⽽const是在 编译、运⾏的时候起作⽤。
define可以⽤来防⽌头⽂件重复引⽤,⽽const不能
#if!defined(AFX_…_HADE_H)
#define(AFX_…_HADE_H)
#endif
答:防⽌该头⽂件被重复引⽤。
5、define⽐较两个值,返回⼩的
#define MIN(A,B) ((A)<=(B)?(A):(B))
6、strlen和sizeof⽐较
strlen返回长度,字符串以'\0'结尾,sizeof为占的字节数
memset:作⽤是在⼀段内存块中填充某个给定的值,它是对较⼤的或进⾏清零操作的⼀种最快⽅法
memcpy:内存拷贝
man使⽤
7、不⽤strcpy拷贝字符串
int a[100],int b[100],i=0;
while(a[i]!='\0')
{
b[i]=a[i];
i++
}
5、冒泡排序:
void bubble_sort(int a[], int n)
{
int i, j, temp;
for (j = 0; j < n - 1; j++)
for (i = 0; i < n - 1 - j; i++)
{
if(a[i] > a[i + 1])
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
}
6、置BIT为1
1<<3=1*(2^3)=8,8>>2=8/(2^2)=2;
/求商,%求余数
#define BIT3 (0x1<<3)
static int a;
void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= ~BIT3;
}
29、分别写出BOOL,int,float,指针类型的变量a 与“零”的⽐较语句。
答:BOOL : if ( !a ) or if(a)
int : if ( a == 0)
float : const EXPRESSION EXP = 0.000001
if ( a < EXP && a >-EXP)
pointer : if ( a != NULL) or if(a == NULL)
30、MJPEG和JPEG区别:
MJPEG:静⽌图像压缩技术,⾼清晰度
JPEG:动态压缩技术,占⽤空间⼩
YUV:原始数据。
32、⽤两个栈实现⼀个队列的功能?要求给出算法和思路!
答 、设2个栈为A,B, ⼀开始均为空.
⼊队:
将新元素push⼊栈A;
出队:
(1)判断栈B是否为空;
(2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;
(3)将栈B的栈顶元素pop出;
这样实现的队列⼊队和出队的平摊复杂度都还是O(1), ⽐上⾯的⼏种⽅法要好
答 、设2个栈为A,B, ⼀开始均为空.
⼊队:
将新元素push⼊栈A;
出队:
(1)判断栈B是否为空;
(2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;
(3)将栈B的栈顶元素pop出;
36. 如何打印出当前源⽂件的⽂件名以及源⽂件的当前⾏号?
答案:
cout << __FILE__ ;
cout<<__LINE__ ;
__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个⽂件中定义的,⽽是由编译器定义的
10、:
设置core⽂件的最⼤值,程序执⾏会产⽣core⽂件,⽤gdb进⾏调试;strace⼯具使⽤
11. 已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是⽬的字符串,strSrc 是源字符串。不调⽤C++/C 的字符串库函数,请编写函数 strcpy。
答案:
/*
编写strcpy函数(10分)
已知strcpy函数的原型是
char *strcpy(char *strDest, const char *strSrc);
其中strDest是⽬的字符串,strSrc是源字符串。
(1)不调⽤C++/C的字符串库函数,请编写函数 strcpy
(2)strcpy能把strSrc的内容复制到strDest,为什么还要char * 类型的返回值?
答:为了 实现链式表达式。 // 2分
例如 int length = strlen( strcpy( strDest, “hello world”) );
*/
#include <assert.h>
#include <stdio.h>
char*strcpy(char*strDest, constchar*strSrc)
{
assert((strDest!=NULL) && (strSrc !=NULL)); // 2分
char* address = strDest; // 2分
while( (*strDest++=*strSrc++) !='\0' )// 2分
NULL;
return address ; // 2分
}
另外strlen函数如下
#include<stdio.h>
#include<assert.h>
int strlen( constchar*str ) // 输⼊参数const
{
assert( str != NULL ); // 断⾔字符串地址⾮0
int len = 0;
while( (*str++) !='\0' )
{
len++;
}
return len;
}
这样实现的队列⼊队和出队的平摊复杂度都还是O(1), ⽐上⾯的⼏种⽅法要好
30、⼀个单向链表,不知道头节点,⼀个指针指向其中的⼀个节点,问如何删除这个指针指向的节点?
答:将这个指针指向的next节点值copy到本节点,将next指向next->next,并随后删除原next指向的节点。
31、
客户端请求消息
客户端发送⼀个HTTP请求到服务器的请求消息包括以下格式:请求⾏(request line)、请求头部(header)、空⾏和请求数据四个部分组成,下图给出了请求报⽂的⼀般格式。默认端⼝80,或者8080
请求⽅法:GET和POST;
⽆连接:⽆连接的含义是限制每次连接只处理⼀个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接
服务器响应消息
HTTP响应也由四个部分组成,分别是:状态⾏、消息报头、空⾏和响应正⽂。
Http状态码:200 ---请求成功 301---资源被转移到其他URL 404----请求资源不存在 505--内部服务器错误
socket编程:
socket(): 调⽤成功返回⼀个⼩的⾮负的整数值,为套接字描述符;失败返回-1
connect(): 激发TCP3次握⼿,返回错误如下:
1、服务器宕机,客户端阻塞recv调⽤,返回ETIMEDOUT ;客户端不发送数据则⽆法检测,使⽤SO_KEEPALIVE检测奔溃
2、服务器奔溃后重启,返回ECONNRESET错误
3、服务器关机,服务端发送⼀个FIN给客户,recv返回0,客户端提⽰服务器过早终⽌,使⽤select或poll检测
bind(): 返回的⼀个常见错误是EADDRINUSE,表⽰地址已使⽤,设置套接字选项SO_REUSEADDR字符串拷贝函数strcpy作用
listen();
accept(); 使服务器接受客户端的请求,将完成队列中的队头条⽬返回给进程,产⽣⼀个新的套接字描述符
数据传输函数:write()函数调⽤成功返回发送的字节数,出错返回-1;read()函数调⽤成功返回接收的字节数
send() :recv();多flags参数,传输控制标志,返回值和write⼀样
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论