学习笔记3:Linux C语言编程基本原理+指针与内存

编程基本原理与操作

单文件编译

gcc -s a.c  //生成汇编语言文件.s
gcc -c a.c  //生成静态库文件.o
gcc a.c     //生成可执行文件.out
 //生成可执行文件,但会报warning

多文件编译

  1. 函数单独写入"max.c"文件,在"hello.c"文件里面加语句 #include "max.c",一起编译即可

  2. 函数头文件分离

输入gcc a.o b.o hello.c -o hello.out生成可执行文件,但会报warning:
在这里插入图片描述
此时需要加入函数声明int max(int a, int b),即可。
但是这样的话,同事并不知道当前的c文件到底要和哪些.o文件一起被编译,所有可以写一个.h的头文件,改头文件里都是函数声明,在住文件中加入#include <min.h>即可

Makefile的使用

在这里插入图片描述
注意Tab,不可以被6个空格或者8个空格替代,输入make,即可自动编译生成对应的所有文件

  • vim 编写的一些命令:
ctrl + w + 下键/上键   //切换窗口
:sp b.c //同时打开b.c文件
:set nu   //打开行号
:wqa      //退出并保存所有文件      

main函数详解

main函数完整形式:

int main(int argv, char *argc[]{}

主函数的代码为printf("argv = %d\n"),输入./main.out,打印argv的值为1;输入./main.out -l,打印argv的值为2。

输入流 stdin,输出流 stdout,错误流 stderr

./a.out 
./a.out > a.txt          //将输出重定向到a.txt,覆盖
./a.out 1>> a.txt        //将输出重定向到a.txt,追加
./a.out >> a.txt         //将输出重定向到a.txt,追加
./a.out < a.txt          //将输入流重定向到a.txt

管道

其中,| 表示管道,grep是文本搜索, ab是文本搜索的内容

ls /etc/ | grep ab        //把前一个命令的输出流 作为第二个命令的输入流
./input.out | ./argv.out  //将第一个的输出作为第二个的输入

指针与内存相关知识

GDB 调试

gdb -g main.c -o main.out  //重新编译 ,生成可以被调试的文件
gdb main.out               //开始调试
l
p 变量名称
bt            //backtrace,查看函数调用信息(堆栈)
f 0           //frame,查看栈帧
start
quit
n  
s	       	  //单步进入
x/3d 0xfffffff  //从0xfffffff开始按十进制输出连续的三个地址内容,默认间隔为4字节

内存管理

  • 32位操作系统最大使用4G内存,因为地址总线是32位,即寻址空间是32位。

  • 地址总线 :有32位,可产生有232种状态,232 = 210 * 210 * 210 * 22 = 1024 * 1024 * 1024 * 4 = 4G

  • 操作系统:对所有的内存条进行编号,编号=唯一的内存字节的地址,一个字节地址存放8bit数据。由于内存的使用不确定,应用程序由操作系统来调用,并对内存做规划。对于64位的操作系统,只分配前48位给程序员,剩下的给操作系统内核。
    在这里插入图片描述

  • 代码段:
    函数编译后存到磁盘,代码编译后的二进制数据保存加载到内存中的代码段

  • 数据段:
    声明的全局变量和常量放在数据段

  • 栈:
    经常能够听到函数栈的说法
    当前调用哪个函数
    函数的参数
    当前调用的函数运行到多少行
    并且这个函数中有哪些变量,这些变量的值是什么(局部变量

  • 堆:
    存放new或malloc出来的对象
    在这里插入图片描述
    在这里插入图片描述

变量和指针的本质

变量名只是一个代号,变量的本质就是内存,指针保存的是内存的地址int *pa = &a在这里插入图片描述
main()函数里面声明的变量在栈里面。
在这里插入图片描述
int类型占4个字节,注意,GCC编译时,会先统一给所有int类型变量分配地址,再是double。。。本处因为是64位机器,故指针占8个字节。
在这里插入图片描述

  • 函数指针
    声明方式:int (*pfunc_name)(int m, int n) = func_name;
    调用方式:int s = (*pfunc_name)(_m, _n);

数组

  • 指针运算
    在这里插入图片描述
    考虑指针偏移,效率很高,比总线查找地址要快很多。
int *p = &a;
p += 3; //默认指针偏移三格
  • 字符数组与指针字符串
    在这里插入图片描述
    打印发现str2是“world”存储的地址,是一个很小的值,在代码段。
    在这里插入图片描述
    若读取的ss长度大于10,会一直覆盖后面的内容:
char ss[10];
scanf("%s", ss);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值