C编程面试笔记
Posted 城子特讯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C编程面试笔记相关的知识,希望对你有一定的参考价值。
01 编译步骤
gcc、g++编译常用选项:
选项 | 含义 |
-o file | 指定生成的输出文件名为file |
-E | 只进行预处理 |
-S | 只进行预处理和编译 |
-c | 只进行预处理、编译和汇编 |
编译成可执行程序经过4步:
1、预处理:宏定义展开、头文件展开、条件编译等,同时将代码中的注释删除;
2、编译:检查语法,将预处理后文件编译生成汇编文件;
3、汇编:将汇编文件生成目标文件(二进制文件);
4、链接:把库链接到最终的可执行程序。
预处理 | gcc -E XX.c -o XX.i |
编 译 | gcc -S XX.i -o XX.s |
汇 编 | gcc -c XX.s -o XX.o |
链 接 | gcc XX.o -o XX |
预处理、编译、汇编、链接的过程 | gcc XX.c -o XX |
02 查缺补漏
-
#include< > 与 #include""的区别:
< > 表示系统直接按系统指定的目录检索;
"" 表示系统先在 "" 指定的路径查找头文件,如果找不到,再按系统指定的目录检索。
-
类型限定符
限定符 | 含义 |
extern | 声明一个变量,extern声明的变量没有建立存储空间。 extern int x;//变量在定义的时候创建存储空间 |
const | 定义一个常量,常量的值不能修改。 const int x = 1; |
volatile | 防止编译器优化代码 |
register | 定义寄存器变量,提高效率。若CPU有空闲寄存器,那么register就生效,如果没有空闲寄存器,register无效。 |
-
函数定义与声明的区别
定义是指对函数功能的确立,包括指定函数名、函数类型、形参及其类型、函数体等,它是一个完整的、独立的函数。
声明的作用则是把函数的名字、函数类型以及形参的个数、类型和顺序通知编译系统(注:不包括函数体),以便在对包含函数调用的语句进行编译时,据此对其进行对照检查。
-
防止头文件重复包含
为了避免同一个文件被include多次,C/C++中有两种方式,一种是 #ifndef 方式,一种是 #pragma once 方式。
方法一:
#ifndef __FILE_H__
#define __FILE_H__
// 声明语句
#endif
方法二:
#pragma once
// 声明语句
-
指针
1、 指针变量指向谁,就把谁的地址赋值给指针变量;
2、指针也是一种数据类型,指针变量也是一种变量;
3、“*”操作符操作的是指针变量指向的内存空间;
4、 &可以取得一个变量在内存中的地址。但是,不能取寄存器变量,因为寄存器变量不在内存里。
5、sizeof()测的是指针变量指向存储地址的大小,在32位平台,所有的指针(地址)都是32位(4字节);在64位平台,所有的指针(地址)都是64位(8字节)。
6、 NULL是一个值为0的宏常量;#defineNULL ((void *)0)
7、const int * p1 = &a; //等价于int const *p1 = &a;修饰*,指针指向内存区域不能修改,指针指向可以变。
8、程序中一级指针最常用,其次是二级指针。二级指针就是指向一个一级指针变量地址的指针。
9、const char *p = buf和char* const p2 = buf;区分为://从左往右看,跳过类型,看修饰哪个字符,如果是*, 说明指针指向的内存不能改变,如果是指针变量,说明指针的指向不能改变,指针的值能修改。
-
内存管理
局部变量。特点:在代码块内部定义的变量都是局部变量;在一个函数内定义,局部变量只在函数范围内有效;在复合语句中定义,只在复合语句中有效。随着函数调用的结束或复合语句的结束局部变量的声明周期也结束。
静态static局部变量。特点:static局部变量的作用域也是在定义的函数内有效;static局部变量的生命周期和程序运行周期一样,同时staitc局部变量的值只初始化一次,但可以赋值多次。若未赋值,则数值变量赋值为0,字符变量赋值为空字符。
全局变量。特点:在函数外定义,可被本文件及其它文件中的函数所共用,若其它文件中的函数调用此变量,须用extern声明。同一文件中,允许全局变量和局部变量同名,在局部变量的作用域内,全局变量不起作用。
静态static全局变量。特点:在函数外定义,作用范围被限制在所定义的文件中;static全局变量的生命周期和程序运行周期一样,同时staitc全局变量的值只初始化一次。
extern全局变量声明。externint X;声明一个变量,这个全局变量在别的文件中已经定义了,这里只是声明,而非定义。
全局函数和静态函数。在C语言中函数默认都是全局的,使用关键字static可以将函数声明为静态,函数定义为static就意味着这个函数只能在定义这个函数的文件中使用,在其他文件中不能调用。(注:不同文件中的staitc函数名字可以相同)。
-
内存分区
5大分区:代码区(text)、数据区(data)和未初始化数据区(bss)、堆区、栈区、常量区。
代码区(text segment):存放要执行的机器指令。代码区是可共享的,其目的是对于频繁被执行的程序,只需要在内存中有一份代码即可。
数据区(data段):该区包含了在程序中被初始化的全局变量、已经初始化的静态变量和常量(如字符串常量)。
未初始化数据区(bss):存入的是全局未初始化变量和未初始化静态变量。未初始化数据区的数据在程序开始执行之前被初始化为 0 或者空(NULL)。
堆区和栈区:堆区用于动态内存分配,由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。栈区用于存放局部变量,函数返回值、参数值;栈是一种先进后出的内存结构,由编译器自动分配释放。
-
文件操作
1、文件结构体
2、打开文件
#include <stdio.h>
FILE * fopen(const char * filename, const char * mode);
功能:打开文件
FILE *fp = NULL;
//打开当前目录(test)下passwd.txt文件
fp= fopen(". / test / passwd.txt", "r");
打开模式 | 含义 |
r或rb | 以只读方式打开一个文本文件(不创建文件,若文件不存在则报错),b是二进制模式 |
w或wb | 以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) |
a或ab | 以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件 |
r+或rb+ | 以可读、可写的方式打开文件(不创建新文件) |
w+或wb+ | 以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) |
a+或ab+ | 以添加方式打开可读、可写的文件。若文件不 存在则创建文件;如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留。 |
3、关闭文件
#include <stdio.h>
int fclose(FILE * stream);
功能:关闭先前fopen()打开的文件。
FILE * fp = NULL;
fp = fopen("xx.txt", "r");
fclose(fp);
4、文件缓冲区了解
系统自动地在内存区为程序中每一个正在使用的文件开辟一个文件缓冲区,从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去,反之磁盘文件到内存亦需要充满文件缓冲区到内存中。
#include <stdio.h>
int fflush(FILE *stream);
功能:更新缓冲区,让缓冲区的数据立马写到文件中。
5、文件顺序读写
-
按字符读写文件
#include <stdio.h>
int fputc(int ch, FILE * stream);
功能:将ch转换为unsigned char后写入stream指定的文件中。
int fgetc(FILE * stream);
功能:从stream指定的文件中读取一个字符
-
按行读写文件
#include <stdio.h>
int fputs(const char * str, FILE * stream);
功能:将str所指定的字符串写入到stream指定的文件中。
char * fgets(char * str, int size, FILE * stream);
功能:从stream指定的文件内读入字符,保存到str所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止,最后会自动加上字符 '\\0' 作为字符串结束。
-
按格式化读写文件
#include <stdio.h>
int fprintf(FILE * stream, const char * format, ...);
功能:根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符 '\\0' 为止。
如:fprintf(fp, "%d %d %d\\n", 5, 10, 15);
int fscanf(FILE * stream, const char * format, ...);
功能:从stream指定的文件读取字符串,并根据参数format字符串来转换并格式化数据。
-
按块读写文件
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:以数据块的方式从文件中读取内容
nmemb:读取文件的块数,读取文件数据总大小为:size * nmemb
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:以数据块的方式给文件写入内容
-
文件随机读写
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
功能:移动文件流的读写位置。
whence:
SEEK_SET:从文件开头移动offset个字节
SEEK_CUR:从当前位置移动offset个字节
SEEK_END:从文件末尾移动offset个字节
long ftell(FILE *stream);
功能:获取文件流的读写位置。
void rewind(FILE *stream);
功能:把文件流的读写位置移动到文件开头。
-
删除和重命名文件
#include <stdio.h>
int remove(const char *pathname);
功能:删除文件
int rename(const char *oldpath, const char *newpath);
功能:把oldpath的文件名改为newpath
-
获取文件状态和文件结尾
#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
功能:获取文件状态信息,buf:保存文件信息的结构体
struct stat
dev_t st_dev; //文件的设备编号
ino_t st_ino; //节点
mode_t st_mode; //文件的类型和存取的权限
nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号
off_t st_size; //文件字节数(文件大小)
unsigned long st_blksize; //块大小(文件系统的I/O 缓冲区大小)
unsigned long st_blocks; //块数
time_t st_atime; //最后一次访问时间
time_t st_mtime; //最后一次修改时间
time_t st_ctime; //最后一次改变时间(指属性)
;
C提供一个feof函数,用来判断文件是否结束。feof函数既可用以判断二进制文件又可用以判断文本文件。
int feof(FILE * stream);
功能:检测是否读取到了文件结尾。
EOF表示文件结束符(end of file);宏定义:#define EOF (-1)
03 总结
这里就是博主关于C编程的面试心得了,后续还会更新更多这类分享,希望大家多多关注。
以上是关于C编程面试笔记的主要内容,如果未能解决你的问题,请参考以下文章
C++笔记--关于string, char*, char[]中的‘
再次爆肝熬夜整理Python编程工具面试题库学习资料总集,结尾自取免费分享