【学习笔记】linux下的c语言的学习

linux下的c语言的学习

c程序的编译过程

.c—->.i—->.s—–>.o文件—->可执行文件
预处理 编译 汇编 链接

  • 预编译过程主要处理源代码文件当中的以#开头的预编译指令,比如#include就是把头文件插入到这个位置

    define就是把所有的宏定义展开,还有就是删除所有的注释

    编译就是把i文件编译成为汇编代码文件,汇编代码扩展名是.s
    汇编就是将汇编语言的代码文件转变成机器语言,只是对照汇编语言的指令和机器语言一条一条翻译过来。

    鏈接,插入代碼庫和啟動代碼。
    gcc -fPIC -shared shared表示产生一个共享对象比如一个静态库libtest.a和一个动态库libtest.so

预处理做了什么?

第一步是展开头文件

编译一个a.c文件,然后看预处理过后文件的样子
gcc -o a.i a.c -E
vim编辑器 a.i

第二步是宏定义

//#define R 10
int a=R;
在.i文件里已经替换

第三步是宏函数

int add(a,b){
return a+b;
}

int e=add(a,b)*add(a,b);
宏函数处理过之后就是int e= a+b*a+b;


typedef 与宏的区别

define R 10

不是c语言可以 结尾
typedef int tni ;
在预处理之后int是不会被替换的
typedef有作用域 define没有
typedef有作用域 define没有

结构体

结构体的声明和定义的三种方法

1.声明和定义分离
struct weapon{
char name[20];
int atk;
int price;
}; //声明
struct weapon weapon_1; //定义
类型名 结构体名
2.同时进行声明和定义,只适用于简单的程序
struct weapon{
char name[20];
int atk;
int price;
}weapon_1;
3.不声明类型名,只能定义一次这种类型的结构体
struct{
char name[20];
int atk;
int price;
}weapon_1;

结构体的初始化:

struct weapon weapon1= {“haha”,10,20};
点运算符(成员运算符,在所有运算符中级别最高)
结构体数组,里面的每一个数组元素都是一个结构体中的所有变量元素。

结构体指针

struct weapon *w;
w=&weapon1;
(*w).name == w->name

共用体/联合体

共用体的成员的地址是一样的
union data{
int a;
char b;
int c;
};
所占字节位=为结构体里最大的那个成员所占的字节

动态数据结构

链表

—静态链表:
头指针指向第一个元素

include

动态链表

malloc分配内存块的函数
sizeof判断数据类型长度符

include

include

c语言运算符

//& | ^ ~ << >>

递归调用

int func(int n){
int r;
if(n<0){
printf(“err”);
}
else if(n==0|n==1){
r=1;
}
else{
r= n*func(n-1);
}
return r;
}

常用vim编辑器的命令

在命令模式时:
按“i” 进入插入(insert)模式 在当前光标前插入
按“a” 进入插入模式 在当前光标后插入
按“shift+a”(大写A)在当前行尾插入
按“shift+i”(大写I) 在当前行首插入
按“o” 在当前光标所在行下起新建一行插入
按“shift+o”(大写O) 在当前光标所在行上起新建一行插入
按“ESC” 返回命令模式
按“x” 删除当前光标的字符
按“dd” 删除当前光标所在行所有字符
“:”+“w” 保存文件
“:”+“q” 退出vim编辑器
“:”+“q!” 不保存退出

pwd
/tmp/cyuyan
c语言默认缩进是四个空格=1个tab
编写好 a.c 文件后使用 gcc a.c编译 生成a.out
执行就是./a.out文件

int max()
{
if(){
}
}
代码排版如上会好看很多

使用sp命令可以新建文件
按ctrl +w +下箭头跳转
set nu 显示行号
数字n +dd 剪切
p粘贴
:wqa 保存所有并退出
gcc max.c hello.c -o main.out
编译两个并且以./main.out输出
并且导入max.c文件

include “max.c”(当前目录下查找)

include

MakeFile 文件

max.o静态编译库文件
max.h头文件

make -v

this is makefile

hello.out:max.o min.o hello.c
tab+两个空格
gcc max.o min.o hello.c

方便项目管理
节约大量编译时间

预编译

int main(int argc,char *argv[])
:argc命令行总的参数的个数
* argv[ ]: 字符串数组,用来存放指向你的字符串参数的指针数组,每一个元素指向一个参数
main完整定义,main参数用于同操作系统交互.
不一定要叫argv或argc.
gcc main.c -o main.out && ./main.out
echo $? 表示你刚刚执行的程序有无正常运行,屏幕输出0 说明正常运行
return 0;也可以用来返回执行的操作
ctrl+s 锁屏
crlt+q 解锁

文件输入输出流

include

include

输出重定向

./a.out >>1.txt
而且不会覆盖源文件
./a.out > 1.txt
会覆盖源文件

输入重定向

./a.out

错误流重定向

echo $?
return 0; right
return 1; wrong

最终结果可以是如下:
./a.out 1>r.txt 2>w.txt

管道

|这个东西就是管道
ps |grep ssh
把ps的输出作为grep的输入

linux c和指针

http://www.centoscn.com/image-text/install/2014/1124/4167.html
centos装gdb
用gdb调试程序
gdb ./main.out
start
p a
n 下一步
p b
n
step 进入
bt查看函数堆栈
f 1 外出和 f 0进入

指针与内存

内存管理

1.C语言的特色在于指针和内存,正事由于C语言对指针和内存的精确调用,使得C语言具有很高的性能。

2.计算机的运行方式:计算机内部计算使用二进制,显示使用十进制,编程的时候使用十六进制。
bytes —字节
1字节=8bit

3.32位操作系统最多使用4G内存,原始是因为CPU最多使用32个地址总线控制内存,而2的32次方就是4G.

为什么32位操作系统只能用4g内存,因为地址总线和寻址空间为32位。

4.操作系统会对所有内存进行编号,这些编号就是内存的地址。计算机通过操作系统控制程序的运行,计算机里面的全部内存,低编码位用来做当作各种应用程序运行所需要的内存,高编码位是计算机内核使用。用户内存从低到高依次是编码段,数据段,堆和栈,堆和栈之间还有一大部分是动态内存。以备不时之需。
计算机–操作系统—程序

5.用户内存隔离的好处在于把操作系统内核所需要的内存和应用程序内存分隔开,就不容易出现卡机或者死机的状态。高位内存空间分配给操作系统内核使用,低位内存空间分配给用户程序使用。
(用户内存和操作系统内存分开)
内存分布图如下:
一.系统内存
二.栈
调用的函数压人栈
栈保存的是函数当前运行时的状态

自由分配的空间(动态课分配)
三.堆

四.数据段 声明一些全局变量,或者一些常量 const int i;int global;
五.代码段 代码编译之后的二进制数据加载到内存中

我们编写的函数在编译后存到磁盘,运行程序时,就把源代码编译后的二进制数据加载到内存空间中的代码段中。声明的全局变量或常量放置在数据段。每次调用新的函数,就将新的函数压入栈区。

指针和变量的本质:

变量的本质是一个代号–就是指向的内存
指针本质也是地址

操作系统对内存的管理

声明若干变量
–把相同类型变量的内存分配在一起
指针所占大小8字节–64位
1.GCC会对内存变量分配进行优化:同一种变量类型会放到一块儿!
2.静态变量、常量、全局变量存于内存的数据段(数据段位置高于代码段)。
3.64位计算机中:地址都是用64bit表示的,所以指针(存储地址)占64bit,即8字节。

函数栈以及数据段内存

地址分配:代码,数据段是从下往上分配(先低地址,后高地址),栈是从上往下分配(先高地址,后低地址)
函数中静态变量,局部变量区别:
局部变量在栈(相对数据段而言的高地址)中,而静态变量在数据段(低地址)中.
所以在多次调用函数时,静态变量不会被重新,初始化. 或者这么说,静态变量的生存周期和数据段相同,局部变量生存时间受调用函数时,所属函数进栈出栈的影响而会重新初始化.

全局变量和静态变量都在数据段中,但静态变量是某个函数特有的.

函数指针也可以调用一个函数
(*函数指针)(形参):函数指针调用方法

字符串与数组

c声明数组需要有长度
int array[2];
//int b=2;
//int array[b]
字符串是以’/000’结束的
堆、栈内存中的内容是以更改的,代码段内存中的内容不允许修改。
实例:
char *str = “apple”;
scanf(“%s”,str);
这是错误的,因为str指向的是代码段内存中的内容,该内容不能进行修改!!
字符串指针(char *str)指向的字符串存放在代码段,而字符数组(char str[])的字符串存放在栈中。
代码段不能被修改,只有在栈内存或者堆内存的数据才能修改。

posted @ 2016-08-07 21:47  Tesi1a  阅读(155)  评论(0编辑  收藏  举报