Skip to content

lingwu-hb/dian_summer_camp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 

Repository files navigation

dian_summer_camp

Expected Behavior

  • (先了解一下怎么做,有了大致想法之后再写一些预期目标)

Current Behavior

7/23

1)当天概述

  • 上午去启明学院搞清楚了后面需要做些什么。
  • 下午补完课后回来熟悉了一下linux中的vim基本操作。(之前太长时间都没使用linux了)
  • 回顾了dian Shell 的一些代码,再次理解了需要做什么。
  • 写了一点点东西,了解一下怎么用g++编译c++多文件系统

2)具体收获记录

  • vim编辑器中可以用d$删除光标所在位置到行尾的内容
  • d0与之相反。x/X快捷键分别是删除后面一个元素/删除前面一个元素!
  • linux中编译运行c++程序。
  • g++ hello.cpp -o hello ./hello
  • 或者gcc hello.cpp -lstdc++ -o hello
  • git 上传文件的全过程
git init
git add
git commit -m ""
git remote add origin git@...
git push -u origin master
  • gcc编译c与文件全过程
1.编译预处理(Processing)
编译器将C程序的头文件编译进来,还有宏的替换
gcc -E hello.c -o hello.i

2.编译(compilation)
将预处理输出文件hello.i汇编成hello.s文件(可编译文件)
gcc -S hello.i -o hello.s

3.汇编(Assemble)
把编译阶段生成的.s 文件转换为二进制目标代码
gcc -c hello.s -o hello.o

4.链接(Linking)
将汇编输出文件hello.s编译输出hello.o文件
gcc hello.o -o hello
  • 头文件中应该书写的内容

1)通过上面的讨论,我们可以了解到,头文件的作用就是被其他的 .cpp 包含进去的。它们本身并不参与编译,但实际上,它们的内容却在多个 .cpp 文件中得到了编译。通过"定义只能有一次"的规则,我们很容易可以得出,头文件中应该只放变量和函数的声明,而不能放它们的定义。因为一个头文件的内容实际上是会被引入到多个不同的 .cpp 文件中的,并且它们都会被编译。放声明当然没事,如果放了定义,那么也就相当于在多个文件中出现了对于一个符号(变量或函数)的定义,纵然这些定义都是相同的,但对于编译器来说,这样做不合法。

所以,应该记住的一点就是,.h头文件中,只能存在变量或者函数的声明,而不要放定义。即,只能在头文件中写形如:extern int a; 和 void f(); 的句子。这些才是声明。如果写上 inta;或者 void f() {} 这样的句子,那么一旦这个头文件被两个或两个以上的 .cpp 文件包含的话,编译器会立马报错。(关于 extern,前面有讨论过,这里不再讨论定义跟声明的区别了。)

但是,这个规则是有三个例外的:

  1. 头文件中可以写 const 对象的定义。因为全局的 const 对象默认是没有 extern 的声明的,所以它只在当前文件中有效。把这样的对象写进头文件中,即使它被包含到其他多个 .cpp 文件中,这个对象也都只在包含它的那个文件中有效,对其他文件来说是不可见的,所以便不会导致多重定义。同时,因为这些 .cpp 文件中的该对象都是从一个头文件中包含进去的,这样也就保证了这些 .cpp 文件中的这个 const 对象的值是相同的,可谓一举两得。同理,static 对象的定义也可以放进头文件。
  2. 头文件中可以写内联函数(inline)的定义。因为inline函数是需要编译器在遇到它的地方根据它的定义把它内联展开的,而并非是普通函数那样可以先声明再链接的(内联函数不会链接),所以编译器就需要在编译时看到内联函数的完整定义才行。如果内联函数像普通函数一样只能定义一次的话,这事儿就难办了。因为在一个文件中还好,我可以把内联函数的定义写在最开始,这样可以保证后面使用的时候都可以见到定义;但是,如果我在其他的文件中还使用到了这个函数那怎么办呢?这几乎没什么太好的解决办法,因此 C++ 规定,内联函数可以在程序中定义多次,只要内联函数在一个 .cpp 文件中只出现一次,并且在所有的 .cpp 文件中,这个内联函数的定义是一样的,就能通过编译。那么显然,把内联函数的定义放进一个头文件中是非常明智的做法。
  3. 头文件中可以写类(class)的定义。因为在程序中创建一个类的对象时,编译器只有在这个类的定义完全可见的情况下,才能知道这个类的对象应该如何布局,所以,关于类的定义的要求,跟内联函数是基本一样的。所以把类的定义放进头文件,在使用到这个类的 .cpp 文件中去包含这个头文件,是一个很好的做法。在这里,值得一提的是,类的定义中包含着数据成员和函数成员。数据成员是要等到具体的对象被创建时才会被定义(分配空间),但函数成员却是需要在一开始就被定义的,这也就是我们通常所说的类的实现。一般,我们的做法是,把类的定义放在头文件中,而把函数成员的实现代码放在一个 .cpp 文件中。这是可以的,也是很好的办法。不过,还有另一种办法。那就是直接把函数成员的实现代码也写进类定义里面。在 C++ 的类中,如果函数成员在类的定义体中被定义,那么编译器会视这个函数为内联的。因此,把函数成员的定义写进类定义体,一起放进头文件中,是合法的。注意一下,如果把函数成员的定义写在类定义的头文件中,而没有写进类定义中,这是不合法的,因为这个函数成员此时就不是内联的了。一旦头文件被两个或两个以上的 .cpp 文件包含,这个函数成员就被重定义了。

7/24

1)当天概述

  • 上午再次复习了一下c++的定义与声明放在.h和.cpp文件中不同位置的问题
  • 下午终于发现哪里有问题了。成功用g++和visual studio编译了c++程序
  • 晚上学习了git的远程仓库版本管理以及其应用

2)具体收获记录

  • 学习运用g++编译c++文件
g++ a.cpp --save-temps//保存中间文件
g++ a.cpp --save-temps -Wall//报出所有可能存在的warning
git log
git log --pretty=oneline
git log --oneline//只显示过去的版本
git reflog//可以显示移动几步回退版本。同时显示过去和未来的所有版本
  • 版本回退命令
使用索引值:git reset --hard [index]
使用^符号:git reset --hard^^^(回退几步)
后退三步或者三步以上,使用~符号:git reset --hard~3
  • reset 的三个参数对比
--soft参数
仅仅在本地库移动HEAD指针

--mixed参数
在本地库移动HEAD指针
重置暂存区

--hard参数
在本地库移动HEAD指针
重置暂存区
重置工作区
  • git diff的使用
1.不加参数表示将工作区和缓存区进行比较
git diff a.txt
2.将文件和本地库中的版本进行比较
git diff HEAD a.txt
3.或者可以和某个历史版本进行比较
git diff HEAD^ a.txt
  • 远程仓库的命令
常用的remote、fetch、push、pull
远程仓库副本的概念。已经理解远程仓库副本与本地/远程仓库的区别

远程仓库副本位于本地,其实一个只读的指针,保存在git的目录里。

7/25

1)当天概述

  • 对自己github里面的远程仓库进行修改(做完刚学过的东西)
  • 上午:研究一下可以如何实现self_git,需要用到哪些方法(文件的操作?)
  • 下午:git的原理深入理解(为后续写代码做铺垫,不然简直毫无头绪)
  • clone 了一个用c#写的仓库,准备通过别人写的仓库找思路。(被迫了解了c#的基本语法)

2)具体收获记录

  • 一些常识
  1. .bat 格式文件:表示批处理文件,双击之后系统会按照文件中的命令逐行执行。
  • git 对于远程分支的操作方法
git fetch [远程库地址别名] [远程分支名]
git merge [远程库地址别名/远程分支名]
git pull [远程库地址别名] [远程分支名]

git默认不会将tags推送到远端分支,可以使用一下命令进行操作
1. 在本地打下标签
git tag 2021-7-25 [commit id不加默认为最新提交版本]
2. 将本地标签推送到远端
git push origin 2021-7-25//推送一个tag
git push origin --tags//推送所有的tags
  • git的原理(如何管理实现命令)
  • .git/object文件中内容 1.blob: 用来保存git里面的内容 2.tree: 用来保存blob的位置(哈希值)以及其它东西 tree里面的格式为: 快照哈希值 blob blob的哈希值 文件名 例如: 100644(本身哈希) blob 58c9...(blob的哈希值) a.txt(文件名) 3.commit:用于存储每次提交的信息(作者以及提交的时间等等)
  • .git/refs里面的内容:HEAD,分支,tag 1.HEAD、分支、以及普通的tag都可以简单的理解为一个指针,指向对应的commit的哈希值。
  • 通过视频了解到了git的工作原理(关键内容) 1)git init:git 会将工作目录下的所有文件拷贝到git本地库中,同时将每一个文件设置为一个blob对象。 2)git add a.txt:git 将所有blob对象的索引(index)加入到暂存区(存放每个blob中的哈希值) 3)git commit -"first commit" a.txt: 第一步:git 根据暂存区中的索引值在本地库中初始化一个 tree 对象,指向所有的blob对象。 第二步:在本地库中创建一个 commit 对象,并让其指向blob对象。(如果之前有提交过的话,还会令commit对象指向上一个commit对象) 第三步:创建分支和HEAD指针,指向commit对象。(如果之前有commit,则更新指针即可)

  • c#的基本语法(与c++的区别)

Possible Solution

  • 前期探索阶段:由于之前只是简单使用过几次git管理,从来没有想过自己实现git,所以免不了经历痛苦的摸索阶段。这一阶段应该要掌握git的操作,同时了解一些基本的实现原理。
  • 中期实现阶段:为了实现git的一些功能,需要将git实现原理和c++的类与面向对象的性质相结合,然后合理设计程序代码,最终完成基本的git功能。
  • 后期完善阶段:(如果有幸能到这个阶段的话)完善程序的功能,补充一些扩展选项命令。

Steps to Reproduce

  1. 通过一些视频和文档了解git的使用以及其原理
  2. 通过看前辈们实现git的程序,获取灵感和思路
  3. 结合c++面向对象的特性进行程序设计,按照自己的想法实现git
  4. 与学长、同学交流,进一步完善代码

Context(Environment)

  • 使用vm虚拟机liunx系统环境下的g++编译器以及visual studio编译器编译运行

Detailed Description

Possible Implementation

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published