笔记:Linux C语言编程基本原理与实践

简介: 笔记:Linux C语言编程基本原理与实践

C语言简介

C语言的标准:ANSI C


C语言的特点:


简单

快速

高性能

兼容性好

功能强大

易于学习

C语言的应用:

1、Linux嵌入式(小工具)(C语言小巧灵活、语法简单、适合做小工具)

linux/unix系统就是由各种各样的小工具集成得来的。


2、和硬件打交道的程序

a、操作系统:苹果系统,安卓系统,windoows

b、ARM嵌入式、单片机、Arduino


3、有高性能要求的应用程序

著名的WEB服务器,NGINX=apache*10


环境

常用指令

# ubuntu 安装vim编辑器
$ apt-get update
$ apt-get install vim
# 编译器
$ cc -v
$ gcc -v

VIM命令模式

i    (插入模式 或 当前光标前插入字符)
Esc     (返回命令行模式)
:w    (保存)
a    (当前光标后插入字符)
:q     (退出VIM)
Shitf + a   (在行尾插入字符)
Shift + i   (在行手插入字符)
o      (下一行插入字符)
Shift + o   (在当前行上行插入字符)
x     (删除单个字符)
dd    (删除整行字符)

C程序

hello.c

#include <stdio.h>
int main(){
    printf("hello world\n");
    return 0;
}

编译执行

# 编译
$ cc hello.c 
# 或者
$ gcc hello.c
# 执行
$ ./a.out

代码分布在多个源文件

1、放在一个文件

hello.c

#include <stdio.h>  // 系统目录中查找
int max(int a, int b){
    if (a > b) {
        return a;
    } else {
        return b;
    }
}
int main(){
    int a = 1;
    int b = 2;
    int ret = max(a, b);
    printf("max value is %d\n", ret);
    // max value is 2
    return 0;
}

编译执行 执行输出文件,默认是a.out

$ gcc hello.c -o hello.out
$ ./hello.out

2、放在多个文件

hello.c

#include <stdio.h>  // 系统目录中查找
int main(){
    int a = 1;
    int b = 2;
    int ret = max(a, b);
    printf("max value is %d\n", ret);
    // max value is 2
    return 0;
}

max.c

int max(int a, int b){
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

多文件编译执行

$ gcc max.c hello.c -o hello.out
$ ./hello.out

此时会有警告

3、声明引用

hello.c

#include <stdio.h>  // 系统目录中查找
#include "max.c"    // 相对目录中查找
int main(){
    int a = 1;
    int b = 2;
    int ret = max(a, b);
    printf("max value is %d\n", ret);
    // max value is 2
    return 0;
}

编译执行

$ gcc hello.c -o hello.out
$ ./hello.out

头文件与函数定义分离

1、两个文件分别编译

gcc参数:

-c compile 只编译源文件但不链接 *.o
-o out 指定输出文件名 默认a.out

分开编译需要注释include

#include <stdio.h>  // 系统目录中查找
// #include "max.c"    // 相对目录中查找
int main(){
    int a = 1;
    int b = 3;
    int ret = max(a, b);
    printf("max value is %d\n", ret);
    // max value is 2
    return 0;
}

编译源文件

# 先编译max.c文件
$ gcc -c max.c -o max.o
# 再编译hello.c文件
$ gcc max.o hello.c

2、三个文件分别编译

min.c

int min(int a, int b){
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

hello.c

#include <stdio.h>
int main(){
    int a = 1;
    int b = 3;
    int maxValue = max(a, b);
    printf("max value is %d\n", maxValue);
    int minValue = min(a, b);
    printf("min value is %d\n", minValue);
    return 0;
}
# 编译min.c
$ gcc -c min.c
# 编译hello.c
$ gcc min.o max.o hello.c -o hello.out

3、引入头文件

min.h

int min(int a, int b);

max.h

int max(int a, int b);

hello.c

#include <stdio.h>  // 系统目录中查找
#include "min.h"    // 引入头文件
#include "max.h"    
int main(){
    int a = 1;
    int b = 3;
    int maxValue = max(a, b);
    printf("max value is %d\n", maxValue);
    int minValue = min(a, b);
    printf("min value is %d\n", minValue);
    return 0;
}

编译执行

$ gcc min.o max.o hello.c -o hello.out
$ ./hello.out

Makefile

# 删除所有.o结尾的文件
$ rm *.o

make工具可以将大型的开发项目分成若干个模块

make内部使用了gcc

$ apt-get install make
$ make -v

Makefile 使用tab缩进

# 注释
hello.out:max.o min.o hello.c
    gcc max.o min.o hello.c -o hello.out
max.o:max.c
    gcc -c max.c
min.o:min.c
    gcc -c min.c

执行编译

$ make
• 1

main函数中的return

main.c

# include <stdio.h>
int main(int argv, char* argc[]){
    printf("hello world\n");
    return 0;
}

查看程序返回

# 编译并执行程序
gcc main.c -o main.out && ./main.out
# 查看程序运行结果
$ echo $?

main函数中的参数

main.c

# include <stdio.h>
int main(int argv, char* argc[]){
    for(int i=0; i < argv; i++){
        printf("argc[%d]=%s\n", i, argc[i]);
    }
    return 0;
}
$ ./main.out name age
argc[0]=./main.out
argc[1]=name
argc[2]=age

argv 参数的个数

argc 参数的内容

标准输入流输出流以及错误流

# include <stdio.h>
int main(){
    // 接收输入
    int a;
    scanf("%d", &a);
    // 输出数据
    printf("input value is %d\n", a);
    return 0;
}
stdin  标准输入 eg: 键盘输入
stdout 标准输出 eg: 终端输出
stderr 标准错误 eg: 错误输出
# include <stdio.h>
int main(){
    // printf("please input a value\n");
    fprintf(stdout, "please input a value\n");
    int a;
    // scanf("%d", &a);
    fscanf(stdin, "%d", &a);
    if(a < 0){
        fprintf(stderr, "the value must > 0\n");
        return 1;
    } else{
        return 0;
    }
}

标准输入输出流以及错误流重定向

加法计算器小程序

接收两个输入,计算两个数字的和,并输出

#include <stdio.h>
int main(){
    int a; 
    int b;
    printf("input a:\n");
    scanf("%d", &a);
    printf("input b:\n");
    scanf("%d", &b);
    int ret = a + b;
    printf("a + b = %d\n", ret);
    return 0;
}

1、输出流重定向

# 追加
$ ./mian.out 1>> a.txt 
# 或者
$ ./mian.out >> a.txt 
# 覆盖
$ ./mian.out > a.txt  

输出结果 a.txt

input a:
input b:
a + b = 8

2、输入流重定向

输入文件 input.txt

3
4
$ ./main.out < input.txt
input a:
input b:
a + b = 7

3、错误流重定向

#include <stdio.h>
int main(){
    int a;
    printf("input value:\n");
    scanf("%d", &a);
    if( a > 0){
        printf("value %d > 0\n", a);
        return 0;
    } else{
        fprintf(stderr, "value %d < 0\n", a);
        return 1;
    }
}
$ ./main.out 1>stdout.txt 2>stderr.txt

4、同时操作标准输入、标准输出、错误流

stdin.txt

-10

执行程序

$ ./main.out 1>stdout.txt 2>stderr.txt < stdin.txt

stdout.txt

input value:

stderr.txt

value -10 < 0:

管道原理及应用

前一个命令的输出,作为后一个命令的输入

# 查看当前目录下文件
ls
# 查看根目录下文件
ls / 
# 查看/etc目录下文件
ls /etc
# 在/etc目录下查找包含ab字符的文件名
ls /etc | grep ab
# 查询进程
ps -e | grep ssh

sum.c

#include <stdio.h>
/**
对输入求和,并输出求和结果和输入个数
格式:sum:count
eg: 400,2
*/
int main(){
    int sum = 0;
    int count = 0;
    int var;
    while(1){
        scanf("%d", &var);
        if(var == 0){
            break;
        } else{
            sum += var;
            count++;
        }
    }
    printf("%d,%d\n", sum, count);
    return 0;
}

avg.c

#include <stdio.h>
/**
对输入计算平均值
格式:sum,count
eg: 500,2
输出:250.000
*/
int main(){
    int sum;
    int count;
    scanf("%d,%d", &sum, &count);
    float avg = sum / count;
    printf("%f\n", avg);
    return 0;
}

input.txt

500
400
600
0
# 编译
$ gcc sum.c -o sum.out
$ gcc avg.c -o avg.out
# 通过重定向输入和管道处理,先求和再计算平均值
$ ./sum.out < input.txt | ./avg.out
500.000000
相关文章
|
3月前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
96 4
|
3月前
|
Ubuntu Linux Python
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
在Linux系统中,使用Tkinter库时可能会遇到中文显示乱码的问题,这通常是由于字体支持问题导致的,可以通过更换支持中文的字体来解决。
189 0
Tkinter错误笔记(一):tkinter.Button在linux下出现乱码
|
19天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
85 13
|
1月前
|
存储 网络协议 编译器
【C语言】深入解析C语言结构体:定义、声明与高级应用实践
通过根据需求合理选择结构体定义和声明的放置位置,并灵活结合动态内存分配、内存优化和数据结构设计,可以显著提高代码的可维护性和运行效率。在实际开发中,建议遵循以下原则: - **模块化设计**:尽可能封装实现细节,减少模块间的耦合。 - **内存管理**:明确动态分配与释放的责任,防止资源泄漏。 - **优化顺序**:合理排列结构体成员以减少内存占用。
141 14
|
1月前
|
监控 算法 Linux
Linux内核锁机制深度剖析与实践优化####
本文作为一篇技术性文章,深入探讨了Linux操作系统内核中锁机制的工作原理、类型及其在并发控制中的应用,旨在为开发者提供关于如何有效利用这些工具来提升系统性能和稳定性的见解。不同于常规摘要的概述性质,本文将直接通过具体案例分析,展示在不同场景下选择合适的锁策略对于解决竞争条件、死锁问题的重要性,以及如何根据实际需求调整锁的粒度以达到最佳效果,为读者呈现一份实用性强的实践指南。 ####
|
1月前
|
缓存 监控 网络协议
Linux操作系统的内核优化与实践####
本文旨在探讨Linux操作系统内核的优化策略与实际应用案例,深入分析内核参数调优、编译选项配置及实时性能监控的方法。通过具体实例讲解如何根据不同应用场景调整内核设置,以提升系统性能和稳定性,为系统管理员和技术爱好者提供实用的优化指南。 ####
|
2月前
|
C语言 开发者
C语言中的模块化编程思想,介绍了模块化编程的概念、实现方式及其优势,强调了合理划分模块、明确接口、保持独立性和内聚性的实践技巧
本文深入探讨了C语言中的模块化编程思想,介绍了模块化编程的概念、实现方式及其优势,强调了合理划分模块、明确接口、保持独立性和内聚性的实践技巧,并通过案例分析展示了其应用,展望了未来的发展趋势,旨在帮助读者提升程序质量和开发效率。
68 5
|
2月前
|
存储 算法 C语言
用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容
本文探讨了用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容,旨在为开发者提供全面的指导和灵感。
53 2
|
2月前
|
关系型数据库 MySQL Linux
Linux环境下MySQL数据库自动定时备份实践
数据库备份是确保数据安全的重要措施。在Linux环境下,实现MySQL数据库的自动定时备份可以通过多种方式完成。本文将介绍如何使用`cron`定时任务和`mysqldump`工具来实现MySQL数据库的每日自动备份。
143 3
|
2月前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。