C语言
文章平均质量分 72
樱满无门
这个作者很懒,什么都没留下…
展开
-
diff命令实现
diff命令实现diff是类UNIX系统下的一个重要的系统工具,用于比较两个文本文件的差异。它有三种输出格式先给大家看看两个用于比对的文件原文file1:aebaghbggfile2:bcdgegjh格式一,普通格式:$ diff file1 file21,6d0< a< e< b< a< g< h7a2,3> c> d8a5> e9a7,8> j> h格式原创 2021-09-20 21:43:24 · 1254 阅读 · 0 评论 -
达夫设备——swtich、while的结合
达夫设备达夫设备是switch语句和while语句结合在一起的一种很精妙的应用,它的主要作用是避开了大量的条件检验,减少了CPU的分支预测带来的性能损耗,主要用在复制大量的数据上虽然在编译技术和CPU技术高速发展的现在,达夫设备的作用已经微乎其微了,但是它仍然给我们提供了一些很好的思路首先,要移动一定数量的数据,最容易想到、也是最简单的方法是:while (n--) { *to++ = *from++;}这段代码中,条件检验的数量和进行数据复制的次数是一样的,都是n次这么做的缺点是,大量的原创 2021-06-29 01:35:46 · 326 阅读 · 0 评论 -
C语言使用GNU扩展实现简单智能指针
C语言使用GNU扩展实现智能指针GNU/C有一个__attribute__扩展叫cleanup:https://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Variable-Attributes.html#Variable-Attributes它的作用是:当某个变量出了它的作用域的时候,自动执行绑定的某个函数这个出作用域,可以是跑出大括号,也可以是其他行为它可以有很多用途,取决于程序员的想象力,但是最直白的、最容易想到的,还是实现一个像C++里一样的智能指针这里有一原创 2021-06-08 10:18:13 · 392 阅读 · 0 评论 -
GLIBC源码——putchar
GLIBC源码——putcharGLIBC源码——从我认为最简单的putchar开始putchar放在putchar.c中,而putchar.c放在libio文件夹里加上注释,一共只有36行#include "libioP.h"#include "stdio.h"#undef putcharintputchar (int c){ int result; _IO_acquire_lock (stdout); result = _IO_putc_unlocked (c, std原创 2021-06-07 12:00:56 · 1380 阅读 · 1 评论 -
libc_hidden_def、libc_hidden_weak、libc_hidden_proto
libc_hidden_def、libc_hidden_weak、libc_hidden_proto在阅读glibc源码的时候,遇见了几个没见过的宏,几乎所有的函数都会使用这几个宏:libc_hidden_def、libc_hidden_weak、libc_hidden_proto因为我比较好奇,所以特地去找了一下有关这些宏的定义(主要也是想多学一点)Linux下学习源码,最方便的地方就是它的各种命令使用find ./ | grep -r "define libc_hidden_def",发现在in原创 2021-06-07 03:49:09 · 2031 阅读 · 0 评论 -
mtrace的使用
mtrace的使用mtrace是Linux下自带的内存泄露检测工具使用方法:在代码中包含#include <mcheck.h>头文件在开始检测的地方写上mtrace()在检测结束的地方协商muntrace()在GCC编译的时候加上-no-pie参数和-g参数在环境变量中设置MALLOC_TRACE,例如export MALLOC_TRACE=./mtrace.log运行程序,程序运行结束后,会生成一个log文件使用mtrace ./a.out ./log查看为什么使用-原创 2021-06-06 22:09:50 · 478 阅读 · 0 评论 -
strong_alias、weak_alias
strong_alias、weak_alias在阅读glibc源码的时候,遇见了几个没见过的宏因为我比较好奇,所以特地去找了一下有关这些宏的定义(主要也是想多学一点)在include/libc-symbols.h中,有我想要了解的两个宏:strong_alias、weak_aliasd的定义#ifndef __ASSEMBLER__/* GCC understands weak symbols and aliases; use its interface where possible, in原创 2021-06-03 21:31:55 · 1405 阅读 · 2 评论 -
动态链接库、GOT、PLT
动态链接库什么是动态链接库以下均为本人自己的理解,不一定正确,但是大致应当是差不多的在很久之前,没有库的概念,每一次写代码都是在从头造轮子后来,人们发现某一些功能是大部分程序里面都要用到的、共通的,且和具体程序没有该关系,例如向控制台打印一个字符等。于是,为了减少写代码的成本,人们把这些实现共通功能的代码汇聚起来,每一次需要使用的时候就用include或者import之类的方法去引用它。再后来,这类代码的量越来越大。这导致了两个问题:1,每一次编译的消耗越来越多;2,实际上并不会用到所有的代码,多原创 2021-06-03 10:36:38 · 559 阅读 · 0 评论 -
Linux下C语言获取网卡信息(IPv4)
Linux下C语言获取网卡信息(IPv4)getifaddrs、freeifaddrsioctlgetifaddrs、freeifaddrsgetifaddr ==> get interface address它将创建一个描述本地网络接口的链表#include <sys/types.h>#include <ifaddrs.h>int getifaddrs(struct ifaddrs **ifap);The getifaddrs() function c原创 2021-05-13 17:49:52 · 1599 阅读 · 0 评论 -
提升程序运行效率的小tips
认识到内存别名的存在消除循环的低效率减少过程调用消除不必要的内存引用消除循环的低效率为了避免不必要的扯蛋和浪费时间,只挑选有必要的和不破坏代码可读性的地方进行学习循环优化指南:如果循环中有要执行多次的值,它又是固定的,最好一次就把它算出来例如,for (int i = 0; i < strlen(s); i ++){ ...}就不是一个好的代码int length = strlen(s);for (int i = 0; i < length; i ++){.原创 2021-02-05 23:10:02 · 85 阅读 · 1 评论 -
printk函数的实现
printf函数的模拟实现:printk在照着教程写内核的时候,需要写自己的printf函数用来打印调试信息,暂且叫它printk函数吧,print kernel的意思实现这个函数的主要难点有两个,一个是变长参数,另一个是格式字符串的判断变长参数,参考这篇文章https://www.cnblogs.com/mysky007/p/11204296.html我把我写的vargs.h亮出来#ifndef INCLUDE_VARGS_#define INCLUDE_VARGS_#define va原创 2021-01-25 11:53:42 · 578 阅读 · 0 评论 -
寒假OS笔记第一天
寒假OS笔记第一天本次寒假的目标:自制一个toy kernal今天准备完成的事情:找到自制OS所需要的资料开始第一行代码寻找资料在知乎的这个专题和这个专题找到了很多很有帮助的回答:https://www.zhihu.com/question/25628124https://www.zhihu.com/question/22463820从中总结出来的是:一个人写一个Demo级别的OS是绝对可行的《30天自制操作系统》这本书只适合beginner,不适合计算机专业的学生看英文材料是必经原创 2021-01-20 12:15:24 · 529 阅读 · 3 评论 -
piece table 的C语言简单实现
piece table 的C语言简单实现piece table的介绍piece table是文本编辑器领域的一个很重要的数据结构能实现文本编辑器的数据结构有很多,例如vi编辑器远古版本使用的一整块数组、块状链表、行链表、数组的改进GAP BUFFER等,还有本文要介绍的piece table。关于文本编辑器的各种实现方式,这篇论文给出了很详细的介绍https://pan.baidu.com/s/1tNuJ6trAStnr52z1QZDR4A关于piece table,这篇文章给出了很详细的说明原创 2021-01-18 15:38:07 · 510 阅读 · 0 评论 -
vi-1.18源码阅读笔记
vi-1.18源码阅读笔记附上源码链接:https://files-cdn.cnblogs.com/files/shiweifu/vi.zipvi_main首先进入主函数主函数一开始给这些变量赋值:CMrc= "\033[%d;%dH"; // Terminal Crusor motion ESC sequenceCMup= "\033[A"; // move cursor up one line, same colCMdown="\n"; // move cursor down one原创 2021-01-17 19:05:54 · 736 阅读 · 0 评论 -
getopt源码寻找尝试
getopt源码寻找尝试getopt函数的作用是简单的参数分析,例如gcc -o main main.c其中,-o称之为option,main称之为optstring,main.c称之为parameterC语言在头文件unistd.h中定义了getopt函数unistd.h是C语言中提供对POSIX操作系统API访问功能的头文件的名称。使用$ vim /usr/include/unistd.h对其进行访问其中有这么一句话:#ifdef __USE_POSIX2/* Get def原创 2021-01-14 12:12:09 · 932 阅读 · 0 评论 -
GObject基本用法
GObject基本用法GObject为C语言提供了面向对象支持安装:sudo apt install libglib2.0-devGObject模拟类的封装为数据类型名称添加一些前缀(PT格式:P——Program,T——数据类型),模拟命名空间所谓数据封装,就是将低层次的元素组合起来,形成新的、高层次实体的技术纯C语言实现双向链表:#ifndef _PROGRAM_LINKEDLIST#define _PROGRAM_LINKEDLISTtypedef struct _Program_原创 2021-01-08 22:27:30 · 1083 阅读 · 0 评论 -
Leetcode 1383 最大的团队表现值(贪心)
Leetcode 1383 最大的团队表现值(贪心)题目公司有编号为 1 到 n 的 n 个工程师,给你两个数组 speed 和 efficiency ,其中 speed[i] 和 efficiency[i] 分别代表第 i 位工程师的速度和效率。请你返回由最多 k 个工程师组成的 最大团队表现值 ,由于答案可能很大,请你返回结果对 10^9 + 7 取余后的结果。团队表现值 的定义为:一个团队中「所有工程师速度的和」乘以他们「效率值中的最小值」。示例 1:输入:n = 6, spee原创 2021-01-04 14:02:55 · 391 阅读 · 0 评论 -
GTK+-3.0学习笔记(三)——Packing
GTK+-3.0学习笔记(二)——Packing参考自官方文档本文基于前两篇文章,主要介绍GTK中的部件打包方式。所有的打包方式见这篇文章本文主要使用一个示例代码对Grid方式进行讲解创建一个grid容器:gtk_grid_new()为窗口增加子容器:gtk_container_add(GTK_CONTAINER(window), grid);为Grid容器增加部件:gtk_grid_attach(GTK_GRID(grid), button, left, top, width, hight)原创 2021-01-01 12:58:12 · 306 阅读 · 0 评论 -
GTK+-3.0学习笔记(二)——helloworld
GTK+-3.0学习笔记(二)——helloworld参考自官方文档在[[GTK±3.0学习笔记(一)——Basics]]中,我们创建了一个没有任何功能的简单窗口。在本文中,我们要完成的工作有:完成一个带有按钮的helloworld窗口程序通过点击按钮关闭该窗口首先放上代码#include <gtk/gtk.h>void activate(GtkApplication * app, gpointer data);void printHello(GtkWidget *but原创 2020-12-31 15:04:58 · 414 阅读 · 0 评论 -
GTK+-3.0学习笔记(一)——Basics
GTK±3.0学习笔记(一)——Basics参考该官方文档这篇文章的目的:创建一个简单的窗口,并籍此简单介绍一个GTK程序是如何运行的。首先,放上代码:#include <gtk/gtk.h>static void activate(GtkApplication *app, gpointer user_data);/** * To create a GtkApplication object and run it */int main(int argc, char *arg原创 2020-12-31 11:51:22 · 470 阅读 · 0 评论 -
Ubuntu下GTK+的下载、安装
Ubuntu下GTK+的下载与安装准备材料:Ubuntu 20.04 LTS(任意Debian系发行版即可)GCC步骤:安装使用sudo apt install libgtk-3-dev进行安装。使用pkg-config --list-all | grep gtk检测是否已经安装得到如下结果:gtk+-broadway-3.0 GTK+ - GTK+ Graphical UI Librarygtk+-x11-3.0原创 2020-12-31 00:10:10 · 2937 阅读 · 0 评论 -
complex network——ER网络的创建(二):G(G, L)
ER网络的创建之G(N,L)法ER网络的创建一般分为两种方法,G(N, p):给定N个节点,每两个节点之间有概率p链接G(N, L):给定L条边,随机放置其中G(N,p)法在ER网络的创建、degree distribution与可视化中接下来进行G(N,L)法的实验大体思路:根据average degree 计算出 L=avgDeg∗N/2L = avgDeg * N / 2L=avgDeg∗N/2,然后随机分配L条边其中最重要的代码如下:void rlatMatInit(Mat_t原创 2020-12-17 18:00:36 · 1176 阅读 · 0 评论 -
排序算法——快速排序
快速排序快速排序 是整个排序算法中速度最快的,也是我所要介绍的最后一种排序方式。它以O(nlgn)O(n\lg n)O(nlgn)的速度雄踞最快的排序方式,并应用在了多种语言中,例如C语言的qsort、C++的sort等,并且局限很小。接下来介绍 快速排序 的主要原理。原理介绍快速排序的主要思想是分治思想(Divide and ConquerMethod)。基本原理是:从数列中取出一个基准数将比这个数大的数字放在它的右边,小于或等于它的数放在它的左边对左右区间重复第二步,直至各个区间只原创 2020-12-16 00:08:40 · 198 阅读 · 0 评论 -
排序算法——基数排序
基数排序基数排序是计数排序的一种改进。计数排序使用一个很长的一维数组进行信息的存储,而基数排序使用一个很大的二维数组进行存储,数组的大小是10*n。10代表十进制,n代表十进制的位数。基数排序的英语是,Least Significant Digit First。又称LSD,从名字就可以看出来,它是从数字的最低位即基位开始进行计算的,比较的趟数是最大数字的位数。而与计数排序最大的不同是,基数排序的对象可以是负数,也可以很大。负数的解决方案:将负数去符号后放在另一个数组中。基本思路:首先计算出数原创 2020-12-16 00:07:19 · 556 阅读 · 0 评论 -
排序算法——计数排序
计数排序计数排序 是一种线性时间复杂度的算法按照理论分析,基于比较的排序算法,时间复杂度的下限是O(nlnn)O(n\ln n)O(nlnn)虽然我也不知道怎么分析出来的,但是确实,不论是快速排序、归并排序、堆排序,它们的时间复杂度都是O(nlnn)O(n\ln n)O(nlnn)但是有这么一种算法,它牺牲了空间来换取时间,得到了线性的时间复杂度与低时间复杂度相对应的,是它的空间复杂度,达到了O(K)O(K)O(K)其中KKK是数据范围这就是计数排序计数排序的主要原理是:记录该数字出现原创 2020-12-16 00:06:11 · 354 阅读 · 0 评论 -
排序算法——堆排序
堆排序堆排序是一种时间复杂度在O(nlnn)O(n\ln n)O(nlnn)的排序方式它利用了一种叫"堆"的数据结构此“堆”非彼“堆”,和内存里面的“堆”、“栈”是不一样的。它是一种基于二叉树的数据结构堆堆的特点是,根结点是子节点的最大值或者最小值子节点的最值全部都堆在根结点上了,所以这个数据结构叫堆(强行自圆其说)介绍一下使用数组模拟二叉树构造堆的方法为什么要使用数组模拟呢?因为在实际的使用中数组比链表更加方便,我不希望为了给几个元素进行排序而写几十行代码来构建一个链表,也不希望大部分时原创 2020-12-16 00:05:07 · 123 阅读 · 0 评论 -
排序算法——猴子排序
猴子排序让一群猴子在打印机前昼夜不停地敲打键盘,最终有可能能输入一部莎士比亚作品集——尽管概论微乎其微。同理,把一堆扑克牌扔到天上,等它们落下来的时候有概率会刚刚好从小到大排成一列。现在有一个无序的数组,我们让一只猴子来帮我们进行排序:#include <stdio.h>#include <stdlib.h>#include <time.h>#include <stdbool.h>#include <string.h>#defi原创 2020-12-16 00:03:35 · 6885 阅读 · 3 评论 -
排序算法——归并排序(Merge Sort)
归并排序归并的英文是:Merge sort其实我们上一节shell排序的论文里面讲到的就是merge sortmerge sort的过程是,将数组分为许多的组,即将粗粒度的数组分为细粒度的数组,然后再将其合并它的优点是,同时对多个数据进行对比排序归并排序是分治法的典型应用分:体现在将数组分为小数组治:对排好序的数组进行合并现在举例对其过程进行分析:source:6, 202, 100, 301,38, 8, 1->divide6, 202, 100, 30138, 8, 1-原创 2020-12-15 13:43:47 · 560 阅读 · 0 评论 -
排序算法——shell排序(希尔排序)
Shell排序Shell排序,又称希尔排序,是我最喜欢的一种排序方式,也是我认为在简单的排序算法里效率最高、在效率高的排序算法里最简单的。(就像我,是成绩差的学生里代码最好的,在代码好的学生里成绩最差的(啊,这个好像没有什么好攀比的))接下来详细讲解下Shell排序的流程、复杂度使用到的网络资料链接:百度百科参考的书籍:C语言K&R首先使用《C语言K&R》上的代码作分析/* shellsort: sort v[0]...v[n-1] into increasing order原创 2020-12-15 13:41:08 · 2528 阅读 · 0 评论 -
动态规划——背包问题(一)
动态规划——背包问题(一)背包问题的基本描述:有nnn件物品,第iii件物品的重量为w[i]w[i]w[i],价值为p[i]p[i]p[i],将这些物品放入一个大小为VVV的背包,要求使得物品的总价值PPP尽量大。则得到P=∑p[i]P = \sum p[i]P=∑p[i]V≥∑w[i]V \geq \sum w[i]V≥∑w[i]当要求物品恰能放入背包时有∑w[i]=V\sum w[i] = V∑w[i]=V背包问题可以分为以下几类,按照复杂程度排序为01背包问题多重背包原创 2020-12-15 13:38:09 · 151 阅读 · 0 评论 -
printf函数是如何隐藏内存错误sysmalloc error
printf函数对内存的作用在写代码的时候,如果出现了动态分配的内存越界,就会报sysmalloc assertion错误(在较低的优化等级下不会出现该错误)但是,在某些时候,如果在恰当的位置添加了printf/scanf函数,那么即使写出了内存越界的代码,也不会报错这个时候,如果某些程序员比较愚笨,他就会认为是编译器错误,甚至认为是C语言的缺陷,因为他发现添加printf和不添加printf的效果差异有那么大,但是其实,主要的错误还是内存越界。使用valgrind可以轻松地进行检测。但是这里有一个原创 2020-12-15 13:36:04 · 306 阅读 · 0 评论 -
基于linux系统的简单malloc模型
在linux系统上的malloc的简单实现本片文章介绍 malloc 在linux系统上的简单实现,仅仅介绍有关原理,不涉及使用mmap等进行大块内存分配有关的部分。背景知识CSAPP第一章中对虚拟内存做了简洁的介绍。为了使进程感觉自己在独占处理器,使用虚拟内存,避免内存冲突。因此我们在下面所讨论的都是虚拟内存而非实际物理内存。linux中的内存分为两部分,一部分是内核空间,分布空间在0xFFFF800000000000 0xFFFFFFFFFFFFFFFF中,另一个部分为用户空间,分布在0x000原创 2020-12-15 13:33:28 · 172 阅读 · 1 评论 -
优化程序性能之优化编译器的能力与局限
优化程序性能本章主要探讨内容:使用几种不同的程序优化技术,让程序运行得更加高效,并且在可维护性与性能间达到平衡。将从以下的几个方面对程序进行优化选择合适的算法与数据结构尽可能使用使编译器更容易产生高效代码的方式来进行程序编写程序优化的第一步应当是消除多余的不必要的工作,包括函数调用、条件测试与内存引用等。这些优化不依赖于目标机器。基于Intel和AMD处理器,本章提出了一种高级模型。还设计了一种图形数据流来对处理器的指令执行形象化,并利用其预测程序的性能。利用处理器提供的指令级别并行能力同原创 2020-12-15 13:32:21 · 503 阅读 · 0 评论 -
程序性能优化之表示程序性能
表示程序性能CPE: Cycles Per Element,每元素的周期数,作为表示程序性能的表示方法处理器活动的顺序由时钟控制,其提供某个频率的规律信号,数量级为GHz使用时钟周期表示,度量值表示的是执行了多少条指令。许多过程含有在一组元素上迭代的循环。void psum1(float a[], float p[], long n){ long i; p[0] = a[0]; for (i = 1; i < n; i ++) p[i] = p[i - 1] + a[i];}原创 2020-12-15 13:29:20 · 561 阅读 · 0 评论 -
BrainFuck的简单解释器
Toy Interpreter of BrainFuck发现了一个很有趣的编程语言:BrainFuck,它的语法很简单,只有6个命令,包括了输入、输出、跳转、加、减功能。这种语言基于一个简单的机器模型,除了指令,这个机器还包括:一个以字节为单位、被初始化为零的数组、一个指向该数组的指针(初始时指向数组的第一个字节)、以及用于输入输出的两个字节流。这种语言,是一种按照“Turing complete(图灵完备)”思想设计的语言,它的主要设计思路是:用最小的概念实现一种“简单”的语言,BrainF**原创 2020-12-15 13:27:13 · 705 阅读 · 0 评论 -
跳表——SkipTable的简单实现
SkipTable的简单实现skiptable是一种高效的数据结构,增删改查的速度和红黑树不相上下,有着广泛的用途,例如大名鼎鼎的redis就是使用了skiptable作为核心的数据结构。skiptable的思想主要是随机化和二分法。首先介绍skiptable的模型长什么样子。它是链表的升级版。链表的查找速度为O(n),而skiptable的查找速度为O(lg n)。skiptable主要在链表上做了以下改动:为每一个元素生成随机的n层索引。level 4: 5level原创 2020-12-15 13:18:01 · 1063 阅读 · 0 评论 -
C语言内存泄漏检测——valgrind-memcheck
Valgrind什么是valgrindValgrind是一套linux下GPL(开源)调试工具集合。包括以下工具:memcheckcallgrindcachegrindhelgrindmassifmemcheck内存检查器主要检查:use of uninitialised memoryreading/writing memory after it has been freedreading/writing off the end of malloced blocksrea原创 2020-12-14 15:17:54 · 787 阅读 · 0 评论 -
排序算法——插入排序
插入排序插入排序是算法导论中介绍的第一个简单排序算法它的流程可以用洗扑克牌来类比:现在你的手上有一些乱序的扑克牌,要将其进行排序先抽出手上的最后一张牌,然后倒着寻找第一张比它小的牌,并插入在那张牌后面接下来重复以上流程,直到所有扑克牌有序为止例子:5 3 8 7 1 9 4 2 65 3 8 7 1 2 9 4 6 // 6 is bigger than 2, and 2 is smaller than 15 3 8 7 1 2 4 9 6 // 6 is bigger than 4,原创 2020-12-14 15:12:04 · 204 阅读 · 0 评论 -
排序算法——冒泡排序
冒泡排序冒泡排序是我学习的第二个排序算法它的特点是,每组所需要的数据都会像吐泡泡一样向上冒出看下面的例子若有一个数组m = [5, 3, 4, 2, 1],将其从小到大排列5 3 4 1 25 3 1 4 25 1 3 4 21 5 3 4 2第一轮排序将1冒泡到最前面1 5 3 2 41 5 2 3 41 2 5 3 4第二轮排序将2冒泡到第二个位置1 2 5 3 41 2 3 5 4第三轮排序将3冒泡到最前面1 2 3 5 41 2 3 4 5最后一轮排序将4原创 2020-12-14 15:09:14 · 165 阅读 · 0 评论 -
排序算法——选择排序
选择排序选择排序是我认为最简单的排序算法基本思想:假设有一个长为N的数组,要将其从小到大排序首先,我找到最小的元素,将其放在第一个位置然后,我在第二个位置到最后一个位置间找到最小的元素,再放在第二个位置…重复以上操作,直到只剩一个元素为止选择排序是很容易理解的接下来分析它的空间复杂度、时间复杂度因为并没有使用额外的空间对数组进行存储,因此其空间复杂度为O(1)O(1)O(1)因为需要两层循环、且每层循环都是对数组的遍历,因此其时间复杂度为O(n2)O(n^2)O(n2)给出其几种代码原创 2020-12-14 15:08:03 · 81 阅读 · 0 评论