数据类型(基本内置类型)
char //字符数据类型
short //短整型
int //整型
long //长整型
long long //更长的整型
float //单精度浮点数
double //双精度浮点数
类型的基本归类
整形家族:
char: unsigned char; signed char
short: unsigned short [int] ; signed short [int]
int: unsigned int; signed int
long: unsigned long [int]; signed long [int]
浮点数家族:
float double
构造类型:
数组类型
结构类型:struct
枚举类型:enum
联合类型:union
指针类型:
int *pi; char *pc; float* pf; void* pv;
空类型:
void表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型
原码、反码、补码
原码
反码:将原码符号位不变,其他位依次按位取反就可以得到反码
补码:反码+1 就得到补码
对于整型来说:数据存放内存中其实存放的是补码(使用补码,可以将符号位和数值域统 一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程 是相同的,不需要额外的硬件电路。)
大小端
大端(存储)模式:数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式:数据的低位保存在内存的低地址中,而数据的高位,保存子啊内存的高地址中。
为什么有大小端模式之分?
为在计算机系统中,我们是以字节为单位的,每个地址单元 都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的short 型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32 位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因 此就导致了大端存储模式和小端存储模式
变量的命名
- 只能由字母(包括大写和小写)、数字和下划线(_)组成
- 不能以数字开头
- 长度不能超过63个字符
- 变量名中区分大小写的
- 变量名不能使用关键字
常量
- 字面常量
- const 修饰的常变量
1、定义变量为常量,一旦赋值,就不能再修改它的值;
2、修饰函数的参数,可以确保在函数体内不能修改这个参数的值,从而提供了更安全的参数传递。
- #define 定义的标识符常量
- 枚举常量
转义字符
\? 在书写连续多个问号时使用,防止他们被解析成三字母词
\‘ 用于表示字符常量'
\“ 用于表示一个字符串内部的双引号
\\ 用于表示一个反斜杠,防止它被解释为一个转移序列符
\a 警告字符,蜂鸣
\b 退格符
\f 进制符
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ddd ddd表示1-3个八进制的数字。如:\130表示字符X
\xdd dd表示2个十六进制数字。如:\x30表示字符0
常见关键字
auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef(类型重命名) union unsigned void volatile while
指针变量
我们可以通过&(取地址操作符)取出变量的内存起始地址,把地址可以存放到一个变量中,这个变量就是指针变量。
野指针:指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
野指针成因:1、指针未初始化 2、指针越界访问 3、指针指向的空间释放
如何规避野指针:指针初始化;小心指针越界;指针指向空间释放,即使置NULL;避免返回局部变量的地址;指针使用之前检查有效性
指针数组
指针数组是指针还是数组? 是数组。存放指针的数组
&arr 表示的是数组的地址,而不是数组首元素的地址。
字符函数和字符串函数
求字符串长度 strlen
长度不受限制的字符串函数 strcpy strcat strcmp
长度受限制的字符串函数介绍 strncpy strncat strncmp
char * strncpy ( char * destination, const char * source, size_t num );
拷贝num个字符从源字符串到目标空间。 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
字符串查找 strstr strtok
错误信息报告 strerror
字符操作
内存操作函数 memcpy memmove memset memcmp
P,P++是P是char类型的时候
移动了一个字节
字节对齐int char int占12个字节。如何缩减字节
通过将int设置为short、使用位图去保存、将字节小的类型放在一块。
逻辑操作有哪些?
与、或、异或
动态内存分配
malloc 和 free
malloc和free都声明在 stdlib.h 头文件中。
C语言提供了一个动态内存开辟的函数
void* malloc(size_t size);
- 如果开辟成功,则返回一个指向开辟好空间的指针。
- 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
- 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
- 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
void free(void* ptr);
free函数用来释放动态开辟的内存。
- 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
- 如果参数 ptr 是NULL指针,则函数什么事都不做。
void* calloc (size_t num, size_t size);
- 函数的功能是为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0.
- 与函数malloc区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全0
void* realloc(void* ptr, size_t size);
- ptr是要调整的内存地址
- size调整之后新大小
- 返回值为调整之后的内存起始位置
- 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
常见的动态内存错误
- 对NULL指针的解引用操作
- 对动态开辟空间的越界访问
- 对非动态开辟内存使用free释放
- 使用free释放一块动态开辟内存的一部分
- 对同一块动态内存多次释放
- 动态开辟内存忘记释放(内存泄露)
文件的打开和关闭
文件指针
FILE* pf; //文件指针变量
通过文件指针变量能找到与它关联的文件。
文件的打开和关闭
FILE * fopen(const char * filename, const char * mode);
int fclose(FILE * stream);
文件使用方式 | 含义 | 如果指定文件不存在 |
---|---|---|
r(只读) | 为了输入数据,打开一个已存在的文本本文件 | 出错 |
w(只写) | 为了输出数据,打开一个文本文件 | 建立一个新的文件 |
a(追加) | 向文本文件尾添加数据 | 建立一个新的文件 |
rb(只读) | 为了输入数据,打开一个二进制文件 | 出错 |
wb(只写) | 为了输出数据,打开一个二进制文件 | 建立一个新的文件 |
ab(追加) | 向一个二进制文件尾添加数据 | 建立一个新的文件 |
r+(读写) | 为了读和写,打开一个文本文件 | 出错 |
w+(读写) | 为了读和写,建议一个新的文件 | 建立一个新的文件 |
a+(读写) | 打开一个文件,在文件尾进行读写 | 建立一个新的文件 |
rb+(读写) | 为了读和写打开一个二进制文件 | 出错 |
wb+(读写) | 为了读和写,新建一个新的二进制文件 | 建立一个新的文件 |
ab+(读写) | 打开一个二进制文件,在文件尾进行读和写 | 建立一个新的文件 |
文件缓存区
const的作用
1、定义变量为常量,一旦赋值,就不能再修改它的值;
2、修饰函数的参数,可以确保在函数体内不能修改这个参数的值,从而提供了更安全的参数传递。
static的作用
Static修饰变量:按照作用范围的不同,变量分为局部变量和全局变量。如果用static修饰变量,不论这个变量是全局的还是局部的都是存储在全局/静态数据区。
- 静态局部变量:使用static修饰符定义的局部变量,即使在声明时为赋初值,编译器也会把它初始化为0。
- 全局变量:只对当前文件可见,其他文件不可见,其他文件可以定义与其同名的变量,两者互不影响。在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。
static修饰函数:使用方式和全局变量类似,在函数的返回类型前加上static,就是静态函数,特性:
- 静态函数只能在声明它的文件中可见,其他文件不能引用该函数
- 不同的文件可以使用相同名字的静态函数,互不影响
#define
1、定义标识符
#define MAX 1000 #define reg register //为 register这个关键字,创建一个简短的名字 #define do_forever for(;;) //用更形象的符号来替换一种实现
#define CASE break;case //在写case语句的时候自动把 break写上。
// 如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。
2、定义宏
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义 宏(define macro)。
#define name( parament-list ) stuff
其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。
3、#define替换规则
1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先 被替换。
2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上 述处理过程。
#和##
1、使用 # ,把一个宏参数变成对应的字符串。
int i = 10; #define PRINT(FORMAT, VALUE)\printf("the value of " #VALUE "is "FORMAT "\n", VALUE); ... PRINT("%d", i+3);//产生了什么效果?
2、## 的作用
##可以把位于它两边的符号合成一个符号。
它允许宏定义从分离的文本片段创建标识符。
宏和函数
属性 | #define定义宏 | 函数 |
代码长度 | 每次使用时,宏代码都会被插入到程序中。除了非常 小的宏之外,程序的长度会大幅度增长 | 函数代码只出现于一个地方;每 次使用这个函数时,都调用那个 地方的同一份代码 |
执行速度 | 更快 | 存在函数的调用和返回的额外开 销,所以相对慢一些 |
操作符优先级 | 宏参数的求值是在所有周围表达式的上下文环境里, 除非加上括号,否则邻近操作符的优先级可能会产生 不可预料的后果,所以建议宏在书写的时候多些括 号。 | 函数参数只在函数调用的时候求 值一次,它的结果值传递给函 数。表达式的求值结果更容易预 测。 |
带有副作用的参数 | 参数可能被替换到宏体中的多个位置,所以带有副作 用的参数求值可能会产生不可预料的结果。 | 函数参数只在传参的时候求值一 次,结果更容易控制。 |
参数类型 | 宏的参数与类型无关,只要对参数的操作是合法的, 它就可以使用于任何参数类型。 | 函数的参数是与类型有关的,如 果参数的类型不同,就需要不同 的函数,即使他们执行的任务是 相同的。 |
调试 | 宏是不方便调试的 | 函数是可以逐语句调试的 |
递归 | 宏是不能递归的 | 函数是可以递归的 |
栈和堆的区别
栈:是一种运算受限的线性表,只允许在表的一段,也就是栈顶进行插入和删除操作。栈分为顺序栈和链式栈两种。因为栈是一种线性结构,所以可以使用数组或链表(单向链表、双向链表或循环链表)作为底层数据结构。使用数组实现的栈是顺序栈,使用链表实现的叫链式栈。两者区别是顺序栈中的元素地址连续,链式栈中的怨怒是地址不连续。
堆:堆是一种常用的树形结构,是一种特殊的完全二叉树,分为大根堆和小根堆。
1、存储内容不同
栈:存放局部变量、函数参数。存放在栈中的数据只在当前函数及下一层函数中有效,一旦函数返回了,这些数据也就自动释放了。
堆:堆中的具体内容可以通过程序员安排
2、分配方式不同
栈:是向低地址扩展的数据结构,是一块连续的内存区域。只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆:是向高地址扩展的数据结构,是不连续的内存区域。
3、空间大小不同
栈:linux下默认的栈空间大小是8M或10M
堆:堆的大小受限于计算机系统中有效的虚拟内存
进程和线程的区别
进程:操作系统资源分配的最小单元。一个进程拥有的资源有⾃⼰的堆、栈、虚存空间(页表)、文件描述符等信息。
1.PID:进程ID,是进程的唯一身份标识,但是它不是固定不变的,是每次启动进程时动态分配的。
2.进程状态:①新建状态(NEW) ②就绪状态 ③运行状态 ④阻塞状态 ⑤销毁状态
3.优先级:决定进程的执行顺序
线程:线程是操作系统能够进行运算调度的最小单元。它被包含在进程中,是进程中实际运行的单位。一个进程中可以并发多个线程,每个线程执行不同的任务 。
优势:创建线程比创建进程快;销毁线程比销毁进程更快;带哦都线程比调度进程更快
进程 VS 线程:
1、根本区别:进程是操作系统进行资源分配的最小单元。线程是操作系统进行运算调度的最小单元。
2、从属关系:进程中包含了线程,线程属于进程
3、开销不同:进程的创建、销毁和切换的开销都远大于线程
4、拥有资源不同:每个进程都有自己的内存和资源,一个进程中的线程会共享这些内存和资源。
5、控制和影响力:子进程无法影响父进程,而子线程可以影响父线程,如果主线程发生异常,会影响其所在进程和子线程。
6、CPU利用率不同:进程的CPU利用率比较低,因为上下文切换开销较大,而线程的CPU的利用率较高,上下文的切换速度快。
7、操作者不同:进程的操作者一般是操作系统,线程的操作者一般是编程人员。
技术面这次我表现的怎么样,这个岗位招多少人,这样判断你自己的竞争力有多大
大学学习方式
在遇到困难后是如何处理的
从项目入手,对Vue的理解,是否使用过组件库
Vue.js是一个用于创建用户界面的开源JavaScript框架,也是一个创建单页面应用的Web应用框架。Vue在构建用户界面时,能够:编写页面的结构,使用基础CSS美化样式;处理用户和界面之间的交互。
对ajax的理解,js如何实现的回调函数
let,var,const的区别,为什么要使用let
相同点:都可以声明变量
不同:
1、var 存在变量提升,另外两个不存在
2、var定义多次变量时,后面所定义的内容会覆盖前面的,但不会报错。let、const所定义的变量出现多次声明后会报错。
3、var、let声明的变量可以再次赋值,而const声明的变量不能再次赋值
4、var声明的变量没有自身的作用域,而let、const声明的变量由自身的作用域
Vue中父类组件如何向子类组件传递信息
整个后端的数据流转过程
你的项目是如何实现的鉴权
对于java反射的理解,什么时候用过反射
MySQL中索引的好处和坏处,都有哪些索引类型,用过哪些
left join和inner join的区别,如果有A表 100条 B表 10条,A left join B 会有多少条记录
1、返回不同。inner join只返回两个表中联结字段相等的行。left join返回包括左表中的所有记录和右表中联结字段相等的记录
2、数量不同。inner join的数量小于等于左表和右表中的记录数量。left join的数量以左表中的记录数量相同。
3、记录属性不同。inner join:不足的记录属性会被直接舍弃。left join不足的记录属性用NULL填充。
SQL优化常用的几种方法
1、对查询进行优化。尽量避免全表扫描,首先应考虑在where及order by涉及的列上建立索引;
2、尽量避免在where子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描
3、尽量避免在where子句中对字段进行null判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null 可以在num列设置默认值0,然后通过=等号查询:select id from t where num=0
4、应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。如:select id from t where num=10 or num=20 此查询可优化为:select id from t where num=10 union all select id from t where num = 20
值传递和引用传递的区别
java中传递数据库对象时是引用传递还是值传递
对hadoop中hive sql和mapreduce的理解,是否使用过
TCP、UDP区别
TCP(Transmission Control Protocol):传输控制协议,是一种面向连接的、可靠的、基于子节流的传输层通信协议
UDP(User Datagram Protocol):用户数据报协议,Internet协议集支持一个无连接的传输协议。UDP为应用程序提供了一种无需建立连接就可以发送封装的IP数据包的方法
区别:
- TCP面向连接,通过三次握手建立连接,四次挥手解除连接;UDP是无连接的,即发送数据之前不需要建立连接,这种方式为UDP带来了高效的传输效率,但也导致无法确保数据的发送成功。
- TCP是可靠的通信方式。通过TCP连接传送的数据,TCP通过超时重传、 数据校验等方式来确保数据无差错,不丢失,不重复,且按序到达;而UDP由于无需连接的原因,将会以最大速度进行传输,但不保证可靠交付,也就是会出现丢失、重复等等问题。
- TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流,由于连接的问题,当网络出现波动时,连接可能出现响应问题;UDP是面向报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低。
- 每一条TCP连接只能是点到点的;而UDP不建立连接,所以可以支持一对一,一对多,多对一和多对多的交互通信,也就是可以同时接受多个人的包。
- TCP需要建立连接,首部开销20字节相比8个字节的UDP显得比较大。
- TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。
如何引用一个已经定义过的全局变量
extern
可以引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变量,假设你将那个变量写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错。
冒泡排序的时间复杂度
O(n^2)交换排序(冒泡、快速)_DalaQL的博客-CSDN博客
堆栈溢出一般是由什么原因导致的
没有回收垃圾资源
JVM虚拟机详解-CSDN博客
SQL Server是否支持行级锁,有什么好处
支持,设立封锁机制主要是为了对并发操作进行控制,对干扰进行封锁,保证数据的一致性和准确性,行级封锁确保在用户取得被更新的行到该行进行更新这段时间内不被其他用户所修改。因而行级锁即可保证数据的一致性又能提供数据操作的进发性。
项目中遇到的难点,如何解决的
规划
面向对象的特征,多态原理
什么是虚函数,怎么实现
多态和继承在什么情况下使用
除了多态和继承还有什么面向对象方法
一个对象=另一个对象会发生什么(赋值构造函数)
如果new之后出了问题直接return。会导致内存泄露,怎么办(智能指针,raii)
多进程fork后不同进程会共享哪些资源
多线程里线程的同步