2019年cvte春招,嵌入式软件开发面试问题分享。
目录
1.scanf 和 gets 的区别?
scanf是格式化输入,如果只使用最简单的格式化字符串%s,那么scanf只会取一个单词,在输入流中遇到空格/tab/换行,就会结束。比如输入流中有"aa bb cc"的话,那么执行scanf("%s", s),s的值就会是aa,再次执行这句话,s的值就是bb,第三次就是cc。scanf会从输入流中取多少怎么取,取决于格式化字符串,也就是scanf的第一个参数;而gets则肯定会取出完整的一行。也就是说在scanf中,换行符等同于空格/tab,但gets中,换行符为读取结束标志。
gets会将输入回车前所有输入的内容取出来,存放到一个字符数组,包括空格/tab,无论这些内容被空格/tab分成了几段,gets都会将这行输入完完整整的放到数组中,通俗点说就是gets会取一行,读到换行为止。
2.#define 比较俩个数的大小,输出小的?
#define out_min(A,B) ((A<=B)?(A):(B))
3.malloc函数需要注意哪些?
- malloc函数原型为
extern
void
*
malloc
(unsigned
int
num_bytes);使用的时候要进行类型转换;
- malloc函数使用后必须free;
4.进程间通信有哪些技术?
-
管道
管道分为未名管道和命名管道,使用时要注意以下几点:
1.管道是半双工的,双向通信需要建立俩个管道;
2.管道从尾部写入,从头部读出;
3.管道里的内容被读出以后,会自动删除;
4.多进程对管道操作时要加锁;
5.读写端关闭的管道返回0;
6.写读端关闭的管道出错,产生信号SIGPIPE;
7.管道空了read会阻塞,管道满了write也会阻塞,可以设置为非阻塞;
未名管道操作流程(框架):
/*未名管道只能用于有亲属关系的进程间的通信*/
int fd[2];
pipe(fd[2]);
pid_t pid = fork();
if(pid < 0){ //error
perror("fork error");
exit(1);
}else if(pid > 0){ //parent
close(fd[0]); //关闭读端
……
close(fd[1]);
wait(0);
}else{ //child
close(fd[1]); //关闭写端
……
close(fd[0]);
}
命名管道操作流程(框架)
/*
* 命名管道可以用于任意俩个进程间通信
* fifo的创建:
* shell下:mkfifo FIFO
* C语言函数:int mkfifo(const char *pathname, mode_t mode);
* 如果该程序创建好了一个管道,那么这个管道就会一直存在;该文件如果已经存在,那么创建就会失败;
*/
//read
fifo_fd = open(fifo_name, O_RDONLY | O_NONBLOCK);
if(fifo_fd < 0){
perror("open error\n");
exit(1);
}else{
printf("open success\n");
}
char readbuff[512];
memset(readbuff, 0, sizeof(readbuff));
while(read(fifo_fd, readbuff, sizeof(readbuff)) < 0){
perror("read error");
exit(1);
}
printf("%s\n", readbuff);
close(fifo_fd);
//write
fifo_fd = open(fifo_name, O_WRONLY);
if(fifo_fd < 0){
perror("open error\n");
exit(1);
}else{
printf("open success\n");
}
char *buf = "123456789";
size_t size = strlen(buf);
if(write(fifo