1.Hello World
vi helloword.c
导入头文件 #include <stdio.h>
main函数 char*argv[]字符数组:
int main(int argc,char*argv[]) {
printf("Hello World!\n")
return 0;
}
编译:gcc 或者mac系统用的 clang -g -o helloworld helloworld.c -g输出debug信息 -o输出可实行程序
ls -alt helloworld
./helloworld
2.常用基本类型
整型:short(短整型占内存空间16位,2个字节) 、int(占内存空间32位,4个字节) 、long(4个字节)
浮点型:float、double 都是32位,double的精度高一些
浮点型会影响运行速度,只要不是科学计算,建议就使用整型
char 一个字节
void 使用指针的时候使用 ps: void*
3.变量与常量 和OC不太一样
int a = 0; //变量,可以再赋值
const int len = 256; // 常量定义 一旦赋值后,不能再改变了
内存管理

4.指针和数组
指针:void* 、char*
指针就是内存中的一个地址
指针本身运算:指针可以通过运算(加减乘除)得到新的地址。
指针所指内容的操作: 计算机系统在管理内存的时候,会将每一个字节进行唯一的编号,通过这个编号就可以拿到我们想访问的内存空间,进行各种操作(加减乘除)。
所谓指针,就是指针的操作,就是我们这些序号的加减乘除,通过这些运算之后可以拿到新的最终想访问的内存地址,拿到地址后,可以做后续的操作(赋值,获取空间里面的内容)。
比如:北京到山东,经过河北中转,才能到山东。
c语言中表述一个指针常见的是char*,字符串有一个首地址 是char*
如果在各种类型之间进行地址的转换,用void*,void不关注具体类型是什么,只关注这事一个地址,由接收人进行解读
数组:数组和指针是息息相关的,某一个地址出开始的,并连续的同一个类型的存储空间称之为数组。char c[2] 、int arr[10]
5.自定义类型-结构体
stuct st{
int a; //成员a
int b; //成员b
}
枚举类型
enum en{
red_color = 0,
yellow_color,
block_color
}
6.算术运算与比较运算
+ 、-、*、/、%
>、==、<、>=、<=
if(a>b){}else{}
for(int i = 0 ; i <100; i ++){}
int a = 0;
while( a<100){
a++;
}
函数
void func (int a) {
...
}
7.文件操作
1.定义文件类型: FILE* file
2.打开文件 FILE* fopen(path,mode); //path 文件的路径 mode 可读/可写/可读可写/新创建
3.关闭文件 fclose(FILE*)
int main(int aegc, char* atgv[])
{
FILE* file;
char buf[1024] = {0, };
file = fopen("1.txt","a+"); //a+ a的游标在末尾,追加的内容添加到文件之后 +是如果文件有就打开,没有就创建
fwrite("hello,world!",1,12,file); //因为是字符串,每一个字符占一个字节,所以填1。 共12个元素,所以填12
rewind(file); // 游标放在文件的开头,然后给buf赋值
fread(buf,1,26,file); //从文件里面读取文件最开头的26个字符赋值到buf里面
fclose(file);
printf("buf:%s\n",buf);
return 0;
}
8.操作系统是如何管理内存的?
1.栈空间:每进入一个函数的时候,操作系统就会给我们分配一小段空间,当我们退出函数的时候,操作系统就会给帮我们将这一小段空间进行回收。一般情况下,栈空间是4M或者8M,不会太大。特性:不需要我们手动去分配和释放空间,而是操作系统帮我们做了这些事。
操作系统操作:压栈(进入函数的时候,它会将所有的参数压入到栈空间里,并且会预留一段空间,当我们在函数里面定义局部变量的时候,它都是在栈空间里帮我们定义的)、弹栈(当我们退出函数的时候,会把栈空间里的内容全部弹出去,所以我们在栈空间定义的局部变量,就会失效。所以我们定义的变量,是有作用域的)
2.堆空间:ps: 32位操作系统,操作系统为每个进程分配的控件是2^32,也就是4G大小。除去1G用于操作系统外,其他的都可以都认为是堆空间。所以如果要分配一大堆空间的话,都是从堆空间。在某一个函数里分配了堆的空间后,只要知道他的地址,在另外一个函数里依然可以找回。
3.内存映射:磁盘中的文件可以映射到内存里。比如硬盘或者U盘里的文件可以映射到内存里,映射之后,我们只要对内存里的内容进行修改,在磁盘中的文件也同时发生了变化。 ---数据库经常用到
9.内存的分配与释放
分配内存 void* mem = malloc(size); malloc在堆空间分配,通过手工的分配。
释放内存 free( mem );
指针实际指向的是一个地址,一般都是堆空间的地址,很少栈空间的地址。
10.内存泄漏和野指针
内存泄漏:不断的向系统申请内存,申请的内存不用,也不释放。(申请的内存一定要成对释放)
野指针:占用别人的内存称为野指针。(指针已经被释放掉,别人会申请内存,有将它拿到别人区域使用了。如果依旧拿该指针访问,该指针就是野指针)
11.函数指针:
和函数非常类似
返回值类型(*指针变量名)([形参列表]);
int func(int x);/*声明一个函数*/
int(*f)(int x);/*声明一个函数指针*/
f=func;/*将func函数的首地址赋给指针f*/
这时,我们可以通过函数指针指向一个函数,函数指针没改,可以输出不同的结果
int sum(int a , int b)
{
return(a+b);
}
int sub(int a,int b)
{
return(a-b);
}
int main(int argc, char*argv[])
{
int result;
int r;
int (*f)(int,int);
f = sum;
result = f(3,5);
f = sub;
r = f(result,5);
printf("3+5=%d\n,8-5=%d\n",result,r);
return 0;
}
12. C语言编译器
GCC/CLANG
1.gcc/clang -g -O2 -o test test.c -I... -L... -|
-g: 输出文件中的调试信息 (出现问题可以单步调试)
-O:对输出文件做指令优化 (指令优化的级别,默认情况是是-O1,不对指令进行优化,如果是-O2,很多的临时变量和局部变量都会被优化掉)
-o: 输出文件的
-I:指定头文件
-L:指定库文件位置
-I:指定使用哪个库
编译过程
1.预编译 (准备工作,在程序里面会引入很多头文件,预编译阶段会把这些头文件和我们的源代码合在一起,形成一个新的文件。最终给编译器进行编译)
2.编译
3.链接,动态链接/静态链接(输出生成的.o文件是中间文件,并不是最终可以拿去执行的程序,实际是可执行程序的一部分,还要与系统的库、第三方库链接在一起-->动态链接和静态链接 静态链接:系统的库或者其他第三方库与我们所编译好的代码链接到一起,形成一个大的文件。动态链接:静态链接是将所有需要的库都放在一起,文件是非常大的,也会造成一些浪费。动态链接是在使用库的时候,直接跳到共享的位置去执行共享的库,在代码的执行过程中进行链接。)
13.生成静态库及引用