Linux下c语言基本原理
1. 要学习一门新的计算机语言,要先了解编程语言的历史及特点,优势何在,这一部分大家可以求助于神通广大的搜索引擎
2. 头文件与函数定义分离
将不会经常修改的函数、公共框架、公共类,先编译打包成静态库,能够提升程序执行效率
#inclue <OS预装的库>
#include “当前项目的源代码” //通常是相对路径
3. make工具的使用
make 工具可以将大型的开发项目分成若干个模块。在Makefile中同样是用gcc来编译程序,遵循GNU协议
1 # This is the Makefile.
2 mxmain.out:mx.o mn.o mxmain.c
3 gcc mx.o mn.o mxmain.c -o mxmain.out
4 mx.o : mx.c
5 gcc -c mx.c
6 mn.o : mn.c
7 gcc -c mn.c
4. main函数的两个参数:int argc, char *argv[]
int argc:1+参数个数 =argv个数 //argument counter
/*
argc表示传入main函数的参数序列或指针,并且第一个参数argv[0]一定是程序的名称,
并且包含了程序所在的完整路径,所以输入的main函数的参数个数应该是argc-1个;
*/
char *argv[] 存放参数内容 //argument vector
5. main函数的返回值
程序执行后若返回0,则表明程序正常执行
gcc main.c -o main.out && ./main.out
echo $? //打印返回值
6. 标准输入流、输出流、错误流
在启动一个应用程序时,OS会提供一系列指向资源的指针,默认创建这三个文件stdin stdout stderr ,分别是标准输入、标准输出、标准错误输出
#include <stdio.h>
/*
* stdin :0
* stdout :1
* stderr :2
*/
int main()
{
//等价于printf("input a number");
fprintf(stdout,"input a number\n");
int a;
//等价于scanf("%d",&a) 数据来源stdin
fscanf(stdin,"%d",&a);
if(0==a){
fprintf(stderr,"a can't be zero");
return 1;
}
return 0;
}
7. 重定向
标准输入流默认键盘,标准输出流默认显示器终端,有时候我们不希望将大量的数据从键盘输入,或是不想将程序输出的结果输出到键盘,那么该怎么做呢?这个时候,重定向的作用就体现出来了
输出重定向>>:不会覆盖文件原来的值,不断追加 适用于日志文件等
输出重定向>: 覆盖原文件
输入重定向<
//示例
./a.out 1>>a.txt //1可省略
ls ../ >>output.txt
8. 管道
管道也称通道:将管道左边的输出流作为管道右边的输入流
ls /etc/ | grep ab
ps -e | grep ssh
9. 指针
* : 取地址
&:取值
int n=5;
int *a=&n;
printf(a); //打印a的内容 即所指向的存储单元的地址
printf("%d",*a); //打印a指向的存储单元的内容
指针偏移:指针自增、自减每次移动的偏移量是指针所指向对象的字节大小
10 字符数组
%s 输出遇到\0就停止
%c 逐个字符输出遇到\0不会停止,但也不会打印任何东西
#include <stdio.h>
int main()
{
char str[]="hello ";//字符数组长度为7
char *str2="world!";
/*str2本质是一个常量字符串
存放在代码段中,不允许程序员修改
不能作指针偏移的加减运算
*/
char str3[10];
printf("input a string!\n");
str[3]='\0';
scanf("%s",str3);
int i=0;
for(i=0;i<7;i++){
printf("%c\n",str[i]);
}
printf("str1: %s\n",str);
printf("str2: %s\n",str2);
printf("str3: %s\n",str3);
return 0;
}
gdb调试工具相关命令
生成可用gdb调试的运行文件 gcc -g
显示源代码 l
重复上一条命令 Enter
开始单步调试 start
执行下一条语句 n
执行下一条语句,若该语句为函数调用,则进入函数,执行其中的第一条语句 s
打印变量的值 p 变量名
查看函数堆栈(函数调用信息) bt
切换函数栈,查看栈帧 f+栈号
打断点 break
退出调试界面 q
Vim中快捷键的使用
命令模式下
保存并退出 :wq
当前光标前插入字符 i
当前光标后插入字符 a
行首插入字符 shift+i
行尾插入字符 shift+a
在下一行插入字符 o
在上一行插入字符 shift+o
删除当前光标处字符 x
删除整行 dd
打开分屏文件 :sp +文件名
分屏跳转 ctrl+w+方向键
显示行号 :set nu
撤销 u
恢复撤销 Ctrl + r
题外话
一些杂七杂八的常识
句柄(Handle)是一个是用来标识对象或者项目的标识符,可以用来描述窗体、文件等,值得注意的是句柄不能是常量
1.只有windows中才有句柄,windows中的句柄是指针的指针,因为windows中对象的经常会在内存中移动(如进行垃圾回收后),所以地址值经常会变,所以就对外提供一个指针的指针即句柄给用户,句柄的地址是不会变的。
2.linux中是没有文件句柄的,只有文件描述符,只是大家习惯把它说成句柄。
3,linux中, 每当进程打开一个文件时,系统就为其分配一个唯一对应的整型文件描述符(从0开始),用来标识这个文件。linux 操作系统通常对每个进程能打开的文件数量有一个限制。默认是1024。
内存地址单位*
1024=1k=2^10
1024k=1M
1024M=1G=2^30
1024G = 1T = 2^40
如何声明函数指针
函数原型int sum(int,int);
那么如何声明该类型函数的指针呢?很简单,将函数名替换成(*pf)形式即可,即我们把sum替换成(*fp)即可,fp为函数指针名,结果如下:
int (*fp)(int,int);
这样就声明了和sum函数类型相同的函数指针fp。这里说明两点,第一,*和fp为一体,说明了fp为指针类型,第二,*fp需要用括号括起来,表明为一个整体,否则就会变成下面的情况:
int *fp(int,int);
这种情况下,意思就大相径庭了,它声明了一个参数为两个int类型,返回值为int类型的指针的函数,而不再是一个函数指针了。