实习接近尾声,其实嘛,收尾工作特别少的!就把本次实习过程遇到的问题或知识点记录下来,供自己将来无聊之时方便回顾。
数组名和指针?
答:数组名可以当做指针使用,因为数组名可以表示改数组第一个元素的地址;但不能将数组名理解成指针,两者区别很大。
内存申请相关函数:malloc、ralloc、free
void * malloc(size_t size); //申请size个字节的内存空间
void *realloc(void * prt,size_t size ); //跳帧之前malloc、calloc、realloc所分配ptr所指向的内存卡大小。
char c = ‘我’ 正确吗?
错误,一个char占一个字节,而一个汉字占3个字节存储。char *c = “我”;
栈空间和堆空间?
答:程序中定义的临时变量,函数运行(用于压栈),等,都是在栈空间;而申请的内存(malloc),一般都是堆空间。
C语言内存映射关系图
内存区域 | 变量数据 | 可读可写性 |
---|---|---|
栈区 | 函数中的普通变量 | 可读可写 |
堆区 | 动态申请的内存 | 可读可写 |
静态变量区 | static修饰的变量 | 可读可写 |
数据区 | 用于初始化变量的常量 | 只读 |
代码区 | 代码指令 | 只读 |
strncpy,strcpy,strlen,strcat,memcpy,memset,strchar,strcmp,strncmp,memcmp?
复合数据类型
结构体:struct,多种变量共同组成。结构体指针使用->符号来选择成员变量。
typdef struct _HELLO_{
int i;
int j;
char hello[1024];
}HELLO,*pHELLO;//取别名
union,联合体,共享内存存储,占内存为最大内存变量所占内存的大小。技巧1:可以巧妙地实现类型转转,因为值存在同一个内存中,用不同的类型去读取表现出来的类型不一样。
enum,枚举,一 一对应的关系,相当于规定变量的取值。
一种神奇的用法:
gmssl中skf接口的外壳;将各个函数指针组合定义成一个结构体,然后申请一个该结构体大小的内存,定义一个指针执行这片内存,利用这个结构体指针来调用各个函数。//这个结构体是由函数指针组成的,这个结构体所占的内存就很小。
位、字节:
位是计算机中最基本的单位,要么是0要么是1,。字节即一个字节,一个字节有8位。比如某些环境(与具体操作系统位数有关)下C语言的char类型就是1个字节,最大255.int是2个字节 16位;long是4个字节 32位。
野指针、空指针、空字符串:
野指针:不知道指向哪里的指针,解引用会非常危险。
空指针:指向NULL的指针,NULL的值为0,其实就是一段根本不会使用的内存。
空字符串:只包含一个’\0’的字符串。
C程序跳转关键字:
#define 定义常量,而关键字const ,将变量转化为常量
/*指针常量*/
int * const p; //指针类型的变量,这个变量指向的指针地址不能修改,但指针地址所指向的内容可以修改。
int a,b;
int * const p = &a;
*p = 3; //正确
p = &b; //错误
/*常量指针*/
const int *p;//常量指针,指向常量的指针,这个指针地址所指向的内容不可以修改,但可以修改指针变量指向的地址。
int a,b;
const int *p = &a;
*p = 3; //报错,常量指针,指向常量的指针,其指向的值不能修改。
p = &b; //正确,常量指针,可以修改其指向的地址。
/*指向常量的常量指针(本质上没有什么意义)*/
位运算:
或 | ;与 & ; 取反 ~;异或 ^
运算操作 | 运算符号 |
---|---|
或 | 就是竖线啦 |
与 | ‘&’ |
取反 | ‘~’ |
异或 | ‘^’ |
C 语言库函数assert()函数
assert(),如果不满足条件,就返回错误,输出一条srderr,然后终止程序。
常用方法:
1. 空指针检查。asser(pointer!=NULL);
2. 检查函数参数的值。如果某参数必须大于0才执行,assert(a>0);如果小于0就返回错误终止程序
【注】:函数判断后,不仅返回错误,还会终止程序哦。
数组指针和指针数组
/*数值指针,指向数组的指针,还是一个指针*/
char *p[4] = "abc"; //数组指针,等价于 char *(p[4]) = "abc";
/*指针数组,成员变量是指针的数组,还是一个数组*/
char (*p)[4] = {"Hello","C","World","!"}; //指针数组,()的优先级最高
C语言错误处理:
// errno;
//perror();
//strerror();
C语言配置文件读取
iniparser.c和iniparser.h是一套小而稳定的配置文件读取函数接口。
解析配置文件ini
C语言测试框架
check是一套C语言测试框架。
check使用方法:开源项目,多看readme,里面有使用的详细过程,结合demo程序,将实现快速上手。
check官网
形参和实参?
形参,定义函数名或函数体的时候使用的参数,目的是用来接受调用该函数时传进来的参数。
实参,在调用时传递给该函数的参数。
【注】:形参智能在被调用时才分配内存单元,在调用结束时,即可释放内存,因此形参智能在函数内部有效,所以形参不能改变实参。
【注】:若想改变实参,方法:1.用指针 2. 用全局变量
main函数
在程序启动时会去找main函数,然后从此开始执行。
int main(int argc,const char * argv[]){
//......
}
//arg = argument ,参数
//argc = argument count ,调用main函数时传递agrv值得个数
//argv = argument value ,
#define typdef
/*
typdef常用来定义一些标识符和关键字的别名,它是语言编译过程的一部分,但不实际分配内存,主要是为了提高程序的可读性
*/
typdef int INT;
typdef int* pINT;
/*
#define是宏定义,不在语言编译过程,在程序预编译过程中完成。
*/
#define A(a,b) ((a)+(b))
#define HW "Hello,World!"
C语言资源大全中文网 :C语言资源大全中文网
/*一套简单的git使用流程*/
git clone -b develop + 地址/版本 //其中-b 是选择分支,版本号非必选,为空则默认最新版本
/*开发工作*/
git add + 某个文件/文件夹 //而我常用的是在VScode添加了git插件,可以方便的单个或多个文件添加。
git status //查看本地库状态,是否有add成功
git commit -m "说明" //添加本次版本修改的一些说明
git push //将本次版本上传至云端
/*git 其他指令*/
git branch //查看分支
git branch -r //查看远端库分支
git branch -a //查看当前所有分支(包括本地分支和远端库分支)
git branch -d AAA //删除分支AAA
git checkout AAA //切换到AAA分支
git pull //取回远程仓库的变化,并与本地分支合并
git rest //重置暂存区,与上一次commit保持一致,但工作区不变
哈哈哈,有点划水了哈,特别少。
mkdir build #创建文件目录
cd build #进入文件目录
ls #查看当前路径下的文件
cd .. #返回到上一级目录
sudo su #普通用户临时申请超级用户权限
sudo + 指令 #以root用户的权限执行本条指令
pwd #查看当前路径
ifconfig #查看ip 和windows下ipconfig一样
cp -a test/ newtest # cp [options] source directory
touch #用于修改文件或目录的时间属性,如果不存在,就立即创建一个。
一个最最简单的makefile例子
main: hello.c mian.c
gcc hello.c main.c -o mian
#最简单的gcc命令: gcc 源程序.c -o 输出目标文件名
makefile中notdir,wildcard和patsubst
1.makefile里的函数
makefile里的函数用法和取变量的值类似,是以’$'开始,然后是一个括号里是函数名和需要的参数列表,若多个参数使用逗号隔开,例如:return = $(functionname arg1,arg2,arg3)
2.notdir
作用:去除所有路径信息,使得SRC里的文件列表只有文件名,没有路径。(主要是消除指令路径下文件名 包含的路径信息)。
3.wildcard函数
使用SRC = $(wildcard*.c ./foo/*.c)
作用:搜索当前目录和指定目录(如 ./foo/)下所有以.c结尾的文件,生成一个以空格间隔的文件名列表,并赋值为SRC。
【注】:当前目录下只有文件名,如(wildcard*.c);而其他目录下的文件要包含路径信息,如(./foo/*.c)
4.patsubst函数
使用OBJ = $(patsubst %.c %.o $(SRC))
作用:patsubst 是匹配替换功能。这句是在SRC中找到所有.c结尾的文件,然后把所有.c换成.o
makefile基础知识一
1. $@ #表示目标文件,包括完整的目标文件名,带有扩展名
$^ #表示所有依赖文件,但不含有重复的依赖文件,以空格隔开
$< #表示第一个依赖文件
反斜杠()是换行符,便于makefile文件的阅读。
2. makefile可以定义变量;这有点像C语言中宏定义字符串
3. makefile自动推到功能,make看到.o文件 会自动将.c文件添加到依赖中,并且gcc -c *.c 也会被推出来
4. PHONY是一个伪目标。
5. 使用make指令,默认make第一个目标。 如果要make其他目标, 使用 make + target
make流程
1.makefile中分为三种: 目标 依赖 代码
2.makefile文件主要包含的5个部分:
1.显示规则:目标 依赖 代码
2.隐式规则:自动推到
3.变量定义: 类似于C语言中宏定义字符串, $() 这样使用变量, 使用函数也是这样的哦
4.文件指示:1.一个makefile引用另外一个makefile 2.指定makefile的有效部分 3.定义多行命令
5.注释。makefile文件只有行注释,#。 可以用反斜杠转移 ,输入# ,如#
makefile中常见预定义变量
AR 库文件维护程序的名称,默认值为ar
AS 汇编程序的名称,默认值为as
CC C编译器的名称,默认值为cc
CPP C预编译器的名称,默认值为$(CC) -E
CXX C++ 编译器的名称,默认值为g++
FC FORTRAN编译器的名称,默认值为f77
RM 删除文件程序的名称,默认值为rm -f
ARFLAGS 库文件维护程序的选项,无默认值
ASFLAGS 汇编程序的选项,无默认值
CFLAGS C编译器的选项,无默认值
CPPFLAGS C预编译器的选项,无默认值
CXXFLAGS C++编译器的选项,无默认值
FFLAGS FORTRAN编译器的选项,无默认值
linux下.a .o .so文件是什么? 有什么作用?
.o 就是objet ,也就相当于windows下编译的obj文件,俗称目标文件
.a 就是archive,也就是相当于windows的VC下编译的lib文件,俗称静态文件。
.o文件是链接文件;.a是静态文件 依靠.o文件生成,作为一个库为外部程序提供函数 接口。
生成.o文件: gcc -c test.o test.c
生成.a文件: ar cqs test.a test.o
.o 就相当于windows里的obj文件,一个.c或.cpp文件对应一个.o文件
.a 是好多个.o合在一起,用于静态链接,即STATIC mode,多个.a可以链接生成一个exe的可执行文件
.so是shared object,用于动态链接的,和windows的dll差不多,使用时才载入。
生成.so文件:gcc -shared *.o -o *.so
C/C++中gcc和g++的对比与区别,及g++的常用参数说明
对比:
1.gcc是GCC中的c编译器,g++是GCC中c++编译器
2.对于后缀是.c的文件,gcc当成c文件处理,而g++当做c++处理;对于cpp文件,都当成.cpp文件处理
3.在编译阶段,g++会自动连接STL库,而gcc必须要加一个参数-lstdc++
4.gcc编译c文件时,可以用的预定义宏比较少。
误区:
1.gcc只能用来编译c文件,g++只能用来编译.cpp文件
2.编译只能用gcc,链接只能用g++
3.gcc不会定义-cpluspuls宏,而g++会。这个宏只是标志着编译器把代码按c还是c++语法解释。
g++常用参数说明:
GCC流程
-预处理(Preprocessing)
-编译(Compilation) :是一个.c文件 或.cpp文件的编译
-汇编(Assembly):将汇编语言转换成二进制
-链接(Linking)
预处理 : g++ -E test.cpp >test.ii # 使用了重定向 , 预处理后生成了一个新的源码,将新的源码重定向输入到test.ii中
编译: g++ -S test.ii #编译预处理后的test.ii文件 ,然后生成汇编代码 test.s
汇编: g++ -c test.s #汇编,将汇编代码转成二进制代码, test.o文件
链接: g++ test.o -o test # 将二级制文件链接成 执行文件 ,即将一个test.o二级制文件链接成一个可执行文件test
linux下默认的头文件和库文件所在位置
库文件: /usr/local/lib
头文件: /usr/local/include
默认链接的配置文件,是在 /etc/下
cmake是一套自动编写makefile的工具, 其语法支持大小写,甚至混写;一般只有全局变量用大写,其余均小写。
#cmake三个基本东西
cmake_minimum_required #最低要求版本
project #设置项目信息
add_executable#指定生成目标
一个例子
# cmake 要求的版本要求说明 如果没有会发出警告
cmake_minimum_required(VERSION 3.0.0)
#设置项目的一些基本信息 。 项目名 开发语言 版本等
project(ssm_skf LANGUAGES C VERSION 1.0.0)
#定义变量 给变量赋值
set(CMAKE_BUILD_TYPE "Debug")
# set(CMAKE_BUILD_TYPE "Release")
# ${}使用定义变量的方法
set(${CMAKE_C_FLAGS_DEBUG} "${CMAKE_C_FLAGS_DEBUG} -DDEBUG") #其实就是gcc后面的各种参数
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
add_definitions(-DDEBUG ) #用于控制 代码的开启 或 关闭
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
#添加头文件路径
include_directories(./src ./inc ./test)
#添加源文件路径 并给其取别名
aux_source_directory(./src SRCS)
#添加定义 用于控制 代码的开启 或 关闭
add_definitions(-D_GNU_SOURCE )
#连接库文件路径
link_directories(./lib ./test/lib)
#生成连接库 并指明其使用的源文件
add_library(${PROJECT_NAME} SHARED ${SRCS})
add_library(${PROJECT_NAME}-static STATIC ${SRCS})
set_target_properties(${PROJECT_NAME} PROPERTIES VERSION 1.0 SOVERSION 1)
set_target_properties(${PROJECT_NAME}-static PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "${CMAKE_SOURCE_DIR}/src/skf_api.h")
# target_link_libraries(${PROJECT_NAME} sqlite3 crypto zlog dl pthread m)
# 连接的库
target_link_libraries(${PROJECT_NAME} sqlite3 crypto zlog dl pthread m rt subunit check)
link_libraries(libsm2_cosign.so libgmp.so)
#添加目标代码源文件路径 并给其取别名 目标代码源文件包含有main()函数
aux_source_directory(./test TEST_SRCS)
#执行 生成可执行文件
add_executable(test_${PROJECT_NAME} ${TEST_SRCS})
target_link_libraries(test_${PROJECT_NAME} ${PROJECT_NAME})
aux_source_directory(./tool TOOL_SRCS)
add_executable(ssmctl ${TOOL_SRCS}) #指定生成目标
target_link_libraries(ssmctl ${PROJECT_NAME})
install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}-static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include)
include(InstallRequiredSystemLibraries)
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_GENERATOR "TGZ")
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
include(CPack)
gdb是linux环境下一个很好用的调试工具
gdb 可执行文件名 // gdb helloc 加载可执行程序准备调试
/常用gdb指令/
指令 | 功能 |
---|---|
r | run 直接调到断点处,没有设置断点的话直接运行程序 |
b 源文件名:fun | 设置一个断点breakpoint在函数”fun”的最开始. 如,b test.c:mian |
b 源文件名:N | 在当前运行源文件的第N行设置断点 |
b 源文件名:N | 在当前源文件file.c的第N行设置断点 |
info break | 显示所有断点信息 |
d N | 删除标号为N的断点 |
c | 继续(continue)运行程序,一直到下一个断点或程序结束 |
f | 运行直到当前函数(function)结束 |
s | 按step调试1行,会进入函数体 (逐步调试) |
s N | 按step调试接下来的N行 |
n | 调试1行,与按s命令不同的是此处不进入函数体(单步调试) |
p var | 输出(print)变量”var”的值 |
set var=val | 设置变量”var”的值 |
bt | 打印调用堆栈(stack trace) |
q | 退出gdb |
指令 | 功能 |
---|---|
cd | 切换目录,如 cd … cd C:\dir1 |
盘号: | 切换根目录,如D: E: |
dir | directory显示当前所处目录下的文件和文件夹 |
md | make directory 创建目录 |
rd | remove directory |
cd | change directory |
del | delete |
exit | 退出 |
cls | clear screen |
shutdowb | 关机指令,如一小时后自动关机,如 shutdown -s -t 3600 |
1.调试
2.lib是一种文件后缀,是windows操作系统的库文件,有静态lib和动态lib两种。
静态lib:将导出的文件的声明和实现都放在lib文件中。
动态lib:相当于一个h头文件,用于支持相应的dll文件运行。
3.dll的使用,分为动态加载和静态加载。(dll动态链接库文件)
动态加载:在程序中用程序显示加载dll文件,通过函数GetProcAddress找到对应的函数地址,利用函数指针直接访问对应的函数,该方案不需要lib文件的支持。
静态加载:只加载对应的lib文件,不加载dll文件。编译只需要lib文件的支持,在运行的时候才调用dll文件函数。此处lib文件和dll文件都放在工程目录下,且需要包含对应的头文件。
4.添加库,添加头文件,添加路径等。
5.
类别 | windows | linux |
---|---|---|
静态库 | .lib | .a |
动态库 | .dll | .so |
编译输出可执行文件 | .exe | 无明显后缀 |
windows:使用静态库时只需要给.exe就可以了,若是动态库,还需要提供.dll(更改dll可以方便更新), 放在可执行文件的同级别下,因为windows首先在当前目录下查找。
vs2010使用静态库 ,需要在附加依赖项中添加lib库名称。【注意】1.包含目录 (头文件等)2. 库目录
6.动态库添加 loadlibrary方法。
一、一些SQL命令
·select -从数据库中提取数据
1.select name country from student
2.select * from student
3.select distinct country from student //返回唯一不同值
4.select * from student where country = ‘CN’ //文本字段
5.select * from student where id = 1 //数值字段
6.select * from student where age > 18 AND country = ‘CN’
7.select * from student where country = ‘CN’ OR country = ‘US’
8.select * from student order by age //升序
9.select * from student order by age desc //降序
·update -更新数据库中的数据
update student age = 20,country = ‘CN’ where name = ‘yzy’
·delete -从数据库中删除数据
1.delete * from student
2.delete * from where age = ‘16’
·insert into -向数据库中插入新数据
1.insert into student values (‘yzy’,18,‘CN’)
2.insert into student (name,country) values (‘yzy’,‘CN’)
·create database -创建数据库
·alter database -修改数据库
·create table -创建新表
·alter table -变更数据库表
·drop table -删除表
·create index -创建索引
·drop index -删除索引
二、SQL另外用法
·SLQ TOP -显示前多少项查询记录,在大型数据表中非常有用
·SQL LIKE 及其通配符
·SQL IN
select * from student where name IN (‘yzy’,‘zy’)
·SQL BETWEEN
select * from student where age between 18 AND 21
select * from student where age NOT BETWEEN 12 AND 18
select * from student where (age between 18 AND 21) AND (name IN (‘Y’,‘Z’))
·SQL 别名
select name AS N ,age AS A from student
select name AS N ,CONCAT(‘age’,‘country’) AS Info from student //合并两项一起显示
·SQL INNER JOIN
·SQL LEFT JOIN
·SQL RIGHT JOIN
·SQL FULL JOIN
·SQL UNION
select name from student UNION ALL select id from school ORDER BY id;
·SQL INTO 创建表并向其中复制数据
select * into student1 from student
select student.name into student2 from student
select student.name student.age into student3 from student
·SQL INSERT INTO SELECT 向一个已存在的表内复制数据
三、哈哈
·实际开发中可以将固定的SQL语句定义为宏。#define