C

标准C语言api,因为c语言的实现是由不同的厂商实现,所以没有标准文档,其中一个开源gnu的libc实现的api地址: https://www.gnu.org/software/libc/
c规范有两种iso c和posix c,其中posix c是iso c的超集。glibc是具体的c规范实现,它即实现了iso c规范,也实现了posix c规范。
============================================================================================
String Literal 叫字符串字面量,或简称字符串。
(关键字,标识符)=(变量,常量,函数)
命令式语言有副作用(side effect):1.函数调用没有返回值,2.赋值表达式,它改变了存储单元的数据,初始化语句没有副作用,int a=3,因为它开辟了新存储空间。
math库在libm.so, 基本库在libc.so, 如果要引用libm.so需要给编译器加-lm,如果需要libc.so则gcc会自动认为需要加-lc
libc.so,libm.so都属于glibc函数库,glibc是c语言库标准的一个具体实现
c89标准:main(){}或int main(){}
c99标准:int main(void){}或int main( int argc,char *args[] ){}
void关键字即可做类型也可以做值,void不能参与运算
全局变量在编译期初始化,所以如果人为初始化必须使用常量表达式,如果没有初始化,编译器会自动赋0

复合类型: 数组,字符串,结构体
数组名不能相互赋值,(语言规范)--数组名做为右值时,自动转换成指向数组首元素的指针。所以数组类型不能做为参数和返回值。
================================================================================================
指针与数组:

int *p; 表示*p表达式的结果是int类型

p作左值表示赋给它一个地址,p作右值表示一个地址

*p作左值表示指针间接寻址被赋值,*p作右值表示指针指向地址里的值

所有指针都指向特定的类型

数组a[i]底层被转为*(a+i)

指针*(p+i)可以等价写为p[i]

指针和数组一个最大不同是:指针是变量,而数组不是,所以数组名不能做为左值,a=p; a++都是不合法的,但是int array[]可以做为形参,做为指针来用。

指针的赋值:如果右值为常量的,则必须为0或者NULL,这两个是等价的,表示无效地址

指针运算:指针与常数的加减运算都是有意义的,表明左移或右移N个元素,同类型指针可做减法运算,指针也可做比较运算。

字符串常量在存储中表示为以'\0'结尾的字符数组

[]的优先级高于*

char *a[]表示a数组的元素存放的是char指针(地址),这种叫做指针数组

指针数组:首先它是一个数组a[],数组的形容词是指针,说明数组的元素是存放的指针(地址)

int (*a)[]表示a是一个指针,指定向了一个int数组,这种叫做数组指针

数组指针:首先它是一个指针*a,指针的形容词是数组,说明指针指向的是一个数组

int (*a)[10]===int b[][10]

int **p表示p是一个指针,它指向一个int *,这种叫做指针的指针。

int (*funVar)()首先funVar是个变量,它是个指针变量,而且是参数为空,返回值为int的函数指针

结构体struct [optionName] {} var1,var2;

结构体做为函数参数时,传递的是实参的副本,所以对于大的结构体应该传结构体指针

struct point p; p.x; struct point *pp; (*pp).x因为结构体指针经常用到,所以使用一种简便方式pp->x

结构体运算符"."和"->",函数调用"()"以及数组"[]"这四种运算符的优先级最高,要高于指针"*"
============================================================================================


============================================================================================
转义为两个方面的作用:
1.将普通字符转为不可打印字符: \n 因为回车为不可见字符,所以得转义
2.将当前语言的字符串界定符转为普通字符: \" 因为"是字符串的界定符,无法直接在字符串里表示,所以转义
============================================================================================
#include必须独占一行
============================================================================================
数据类型
============================================================================================
常量:每种常量都有类型,字符串常量全称是字符串字面量常量,没有相应的数据类型,它可以用字符指针接收。
变量:每种变量都有类型,变量名代表存储器中一块命名的空间,空间大小由变量类型大小决定
============================================================================================
定义是声明中的一种,如果一个声明要求分配存储空间,那这个声名就是定义
表达式:每个表达式都有值,每个表达式都有右值,但只有变量的表达式存在左值,(a=b)=c不合法,因为a=b表达式没有左值
表达式运算过程中类型自动转换规则
函数调用和表达式的副作用,改变存储单元里的数据或者做输入输出操作都算是副作用。
无论是函数还是变量,都是先声明后使用。
============================================================================================
c标准包含语法部分和标准库两部分,c标准库的gcc实现glibc,里面的基础文件是libc.so
============================================================================================
void关键字为何而存在:
任何表达式都有值,函数调用也是表达式,如果函数没有必须返回东西,但必须有返回值,所以有了void,它即是类型,也是值,void不能参与任何运算
============================================================================================
局部变量可以用常量或表达式来初始化,但全局变量只能用常量初始化。
局部变量没初始化,则初始值是不确定的,全局变量没初始化,编译器会给个默认值(0,null)
============================================================================================
变量的作用域:表示变量在哪个代码区间能被访问到。
每次都有点区别的重复工作叫做迭代,迭代分为递归和循环。
预处理指令,在编译前的预处理阶段已经被cpp(c preprocessor)处理,所以预处理指令不会被编译
============================================================================================

si: step one instruction exactly
disassemble: disassemble current function
info registers: current registers info
观察点(Watchpoint)用来设置访问某一存储单元时中断,例如:watch input[5]
x/7b input 指令表示:打印input数组的前7个字节。
x/20 $esp: 查看esp指向内存中的20个32位数。

============================================================================================
============================================================================================
elf的三种类型:可重定位文件,可执行文件,共享库文件
readelf -a sample.o查看elf类型的文件。
hexdump -C sample.o查看二进制文件。
objdump -d sample.o 反汇编.text section
nm a.out表示查目标文件的符号表
gcc -S sample.c 生成汇编代码
低地址存放低位数,称为小端序, 反之为大端序
.shstrtab段里存放着各section的名字,例如(.text,.data,.bss)
.strtab段里存放着程序中的标识符的名字
.rel.text段里存放着需要链接器重定位的地址
.symtab段里存放着符号表

函数调用:
地址空间:
地址空间上面是高地址,下面是低地址。stack和mmap是从高往低,heap是从低往高。
esp指向栈顶,ebp是栈桢的栈底。
call调用之前:
将call的参数入栈, ie(两个参数:3和4):sub $0x8, %esp; movl $0x3, 0x4(%esp); movl $0x4, (%esp) 
调用call 80483aa:
先将call的下一条指令地址80483e9入栈,再修改eip的地址为80483aa处执行。
进入 80483aa函数:
将ebp入栈push %ebp, 再将栈底设为当前esp, mov %esp, %ebp
读取上个桢栈的两个参数取出放入本栈中,求和。
函数返回:
leave指令,是push %ebp和mov %esp,%ebp的逆操作,将ebp和esp设为上个桢栈的栈底和栈顶。
ret指令,是call指令的逆操作,将上个桢栈中保存的下一指令地址80483e9赋值给eip
============================================================================================
============================================================================================
main函数是被crt1.o中的_start函数调用。

============================================================================================
============================================================================================
函数内的变量为局部变量,在函数外的变量为全局变量。局部变量的可访问范围(作用域)只限于本函数,全局变量整个程序都可访问。
const修辞的变量表示是只读的,一般在.roldata section,它与.text section合并到同一个segment。一般程序里的字符串字面量也会放在.rodata section。
static修辞的变量表示不论该变量是局部还是全局的,它的生命周期和程序一样长,即这些变量(即使是局部变量)会放在.data section。但是这些变量在符号表中的type是local的,表示不被链接器处理,即这些变量(即使是全局变量)也只能在当前目标文件访问,而不能被其它目标文件链接上。
一个字符串的局部变量,它也是在栈上分配空间,ie: char b[]="hello, world";
register修辞的变量表示:尽量将该变量保存在寄存器中。
external+标识符(变量或函数原型)的声明,表示当前文件要使用外部文件的全局标识符。

============================================================================================
库文件名都是以Lib打头的,静态库是以.a的后辍,表示Archive。
静态库打包命令:ar rs libstack.a stack.o ....
如何使用静态库: gcc main.c -L. -lstack -Istack -o main : -L表示库目录, -l(小写L)表示链接 libstack 库, -I(大写i)库的头文件目录
gcc -print-search-dirs表示编译器默认查找的库目录列表
共享库编译:gcc -c -fPIC stack.c push.c pop.c
共享库打包:gcc -share -o libstack.so stack.o push.o pop.o
ldd a.out查看当前可执行文件依赖哪些库文件
如果程序使用了共享库,那么该程序必定依赖ld-linux.so
如何使用共享库:设置共享库的路径的几种方式:1.通过ldconfig命令,2. 直接将自定义共享库放在/urs/lib或/lib目录下,因为ldconfig的默认路径就是它们。再使用命令:gcc main.c -L. -lstack -Istack -o main(虽然编译时指定-L指明自定义共享库位置,但在运行时ld-linux.so不知道自定义共享库位置,所以先要设置自定义共享库的路径)
动态链接的过程:对于调用共享库的全局标识符(全局变量和函数),程序里的调用代码都不是直接指向标识符的地址,而是通过好几步,调转到ld_linux.so处,由它来找出标识符在共享区的地址给程序。
每个共享库都有三个名字:
real name: libcap.so.1.10
soname: libcap.so.1 只包含主版本号(.dynamic section中存放的就是soname)
linker name: libcap.so
查看某一程序的地址空间: cat /proc/[pid]/maps



============================================================================================
MMU里面有两个部件,一个是分段部件,一个是分页部件,对应了两个机制:分段机制和分页机制。linux绕开不使用分段机制,只使用分页机制。
MMU处理逻辑地址->线性地址->物理地址
============================================================================================
内存映射I/O:指in,out端口不是独立的。
内存映射(mmap):将一个文件或其它对象映射进内存。
swap:

指针:本质是一个整型数,它的值是一个地址。
*号叫间接寻址运算符。*pi = *pi + 10;
指针一定要赋值,再使用,例如:int *p; *p=0;这是错误的。如果没有值,赋值NULL, #define NULL ((void *)0)
void *类型:是通用指针类型,它的值的类型的确定的,为整型,它可以与什么明确的指针类型隐式转换。char a = 'A'; void *v=&a; char *p=v; printf("%c",*p); 
而void类型的变量是无法使用的,因为不知道void类型变量所占的空间大小。
函数指针:void (*f)(const char *) = say_hello;


"
对'xxxx'未定义的引用
"
如果出现这个错误是因为gcc时程序源代码必须放在静态库的前面。


每一个进程都有一个工作目录。

预编译:
#define是给右边的参数起个别名为左边的参数
typedef是给左边的参数起个别名为右边的参数
typedef的用途:
1. 明确意图,简化代码。
1.1定义: typedef char* PCHAR; 使用: PCHAR pa ;
1.2定义: typedef struct tagPOINT  {  int x;   int y;  }POINT; 使用: POINT p1;
1.3函数声明的简化。
2. 跨平台:不同平台对实数类型支持不一样,可以定义typedef long double REAL;  这样如果该程序在其它平台运行,只用修改typedef文件typedef float REAL;,所有引用REAL都会改动。

__cdecl,__fastcall, __stdcall:
表示三种不同的 表示不同的堆栈调用方式和释放方式
__cdecl 按从右至左的顺序压参数入栈,由调用者把参数弹出栈
__stdcall按从右至左的顺序压参数入栈,由被调用者把参数弹出栈
__fastcall头两个DWORD类型或者占更少字节的参数被放入ECX和EDX寄存器,其他剩下的参数按从右到左的顺序压入栈。由被调用者把参数弹出栈
  




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的高校科研信息管理系统实现了操作日志管理、字典管理、反馈管理、公告管理、科研成果管理、科研项目管理、通知管理、学术活动管理、学院部门管理、科研人员管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让高校科研信息管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值