计算机基础知识学习笔记
计算机基础知识学习笔记。
发现自己打比赛适应能力很差。。。常常没有 devc++ 就打不好(主要是用不惯 gedit/vscode),因此决定先来学学计算机基础知识(
1. 操作系统
操作系统,说白了就是一个有独立的文件系统、驱动程序,能够独立分配内存并与使用者进行交互的电脑程序,自主调用硬件资源。我们熟知的 Windows、Linux 就是操作系统,其他操作系统有 MacOS、iOS、Android 等。
当然,由于我们默认的操作系统是 windows,因此如果需要其他操作系统的环境(如 linux),就需要虚拟机的帮助才能运行。虚拟机是指能够在完全隔离的条件下模拟一个操作系统的环境的软件。举个例子,通过将 linux 系统的环境保存在一个后缀名为 .iso
(虚拟光驱)的文件中,再用虚拟机为该系统分配一定的硬盘与内存就可以模拟虚拟的 linux 环境了,我们常听说的“在 linux 下评测”就是指该虚拟的 linux 环境。常用的虚拟机有 VMware Workstation,Virtual PC,Oracle VM Virtualbox(譬如在我原来的电脑上是 VMware,在学校电脑上是 Oracle)。
对于一个操作系统而言,为了使其能够灵活调用硬件资源,需要驱动程序的驱动作用才能得以进行。驱动程序,说白了就是沟通硬件与计算机的程序。一个打印机之所以无法在新电脑上使用,是因为该电脑上没有该打印机的驱动程序。windows 的驱动程序可以在目录 C:\Windows\System32\drivers
下找到。注意,CPU、内存、主板、软驱、键盘、显示器等设备并不需要安装驱动程序,而声卡、显卡、网卡等程序则需要。
没有用户的指令,操作系统不会随意调用软件和分配内存,在图形界面出现之前,用户则是以命令行的形式向计算机发送指令的,Windows 的命令提示符 cmd.exe 可以通过 Win+R 然后输入 cmd,Linux 下的终端可以通过 Ctrl+Alt+T 打开。操作系统的终端本质上是一种 Shell。或者说,Shell 是一个程序,一个二进制可运行可执行的程序,它能够处理人类用户下达的命令。而每次我们打开终端,系统就会自动开始调用这个程序。
2. Windows 命令行的使用
终于来了点和 OI 沾得上边的东西了(
正如上面提到的,windows 的 cmd.exe 实际上是一种 shell,因此它也有对应的语法。更具体地,shell 其实是一种脚本语言,类比 c++ 的 .cpp
文件,以 .bat,.cmd
为后缀名的文件则可以视作用 shell 为语言写出来的源代码。每次运行这样的 .bat
文件时,系统就会将该文件中的所有命令扔到 cmd.exe 中一行行执行,这也就是所谓“脚本语言”的含义,通俗地来说就是按照代码顺序一行一行将其翻译成机器能够识别的信息,常见的解释语言还有 Python、PHP 和 JavaScript(.js 文件)。常见的语言类型有机器语言(即用 01 写成的、机器能够直接识别的语言)、汇编语言(则用 add,mov
等简单助记标识符写成的,直接与内存相关的低级语言)、高级语言(独立于机器,面向过程或对象的语言,脚本语言就是一种解释型的高级语言,即翻译一句,执行一句,除此之外还有编译型的高级语言,即先将其翻译成汇编语言,再通过静态与动态链接生成可执行文件,常见的编译型语言有 C、C++、Fortran、Pascal,而 C# 和 Java 则是介于编译型和解释型之间的语言)
那么 DOS 命令行的语法究竟有哪些呢?
cls
命令(Linux 底下为clear
):无参数,用于清除屏幕cd
命令:任意时刻,命令行都会有一个路径表示当前位于什么目录之下,cd
命令则可以指定一个子目录并让命令行进入这个子目录。譬如cd Desktop
则可以进入桌面。dir
命令(Linux 底下为ls
):显示当前目录中的子目录及文件的信息。fc
命令(Linux 底下为diff
):fc A.txt B.txt
表示比较A B
两个文件的内容,如果相同则会提示”找不到差异“,否则会列举两个文件的不同之处。该命令常在对拍中出现。在后面加上/w
可以忽略空格和 tab,在后面加上/c
可以忽略大小写问题。譬如,如果 A.txt 的内容为A[space]
,B.txt 内容为a
,那么fc A.txt B.txt /c /w
则会提示”找不到差异“。mkdir
命令:rename A
表示新建一个叫A
的目录。rm
命令:删除文件/目录:rm -r A
删除名叫 A 的目录,此命令会将 A 在文件搜索树中的所有子目录递归删除。rm -f A.txt
删除名叫A.txt
的文件。值得注意的是,在这条命令中,A.txt 中可以含通配符,例如rm -f *.txt
表示删除所有后缀名为.txt
的文件。
rename
命令:rename A B
表示将 A 重命名为 B。echo
命令:echo A>B.txt
表示向 B.txt 输出 A。A.exe
表示运行可执行文件A.exe
,当然后面可以跟一些参数,这些参数会被传到 main 函数的参数之内,argc 表示参数个数,argv 表示参数内容。譬如在使用 checker 的使用我们会调用checker.exe in.txt out.txt ans.txt
,此时 \(argc=3\)。
当然还有一些和 g++ 有关的编译命令。要使用这些命令,就必须加入配置 g++ 的环境变量,这里就不赘述了,毕竟真实考场上的机子肯定是事先就配好环境变量的。
最常用的与 g++ 有关的命令是 g++ a.cpp -o a.exe
(Linux 底下把 .exe 去掉)表示用 g++ 标准编译 a.cpp 并生成可执行文件 a.exe。那么这四些参数究竟有什么用呢?这就需要我们从 g++ 将源代码转化成可执行文件的过程入手了。
首先贴一张图片(来自 https://blog.csdn.net/a3192048/article/details/90143629):
从图片中我们很清晰地看到,源文件生成可执行文件的过程,经历了预编译/预处理,编译,汇编,链接这四个过程。经过四种操作生成的文件分别被称为“预处理代码”、“汇编代码”、“目标代码”和“可执行文件”。
让我们来着重查看四个阶段,首先是预编译阶段,假设我们现在有这么一个 g++ 程序:
tmp4.cpp
//Created time: 2022/3/16 14:08:12
#include <cstdio>
int a,b;
int main(){
scanf("%d%d",&a,&b);
printf("%d",a+b);
return 0;
}
我们首先执行命令 g++ -E tmp4.cpp -o tmp4.i
,然后我们打开 tmp4.i
,由于篇幅原因,放上最后几行:
static __attribute__ ((__unused__)) __inline__ __attribute__((__cdecl__))
__attribute__ ((__nonnull__ (2)))
int swprintf (wchar_t *__stream, const wchar_t *__format, ...)
{
register int __retval;
__builtin_va_list __local_argv;
__builtin_va_start( __local_argv, __format );
__retval = vswprintf( __stream, __format, __local_argv );
__builtin_va_end( __local_argv );
return __retval;
}
}
# 825 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/stdio.h" 2 3
# 834 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/stdio.h" 3
__attribute__ ((__dllimport__)) wchar_t *__attribute__((__cdecl__)) _wtempnam(const wchar_t *_Directory,const wchar_t *_FilePrefix);
__attribute__ ((__dllimport__)) int __attribute__((__cdecl__)) _vscwprintf(const wchar_t * __restrict__ _Format,va_list _ArgList);
__attribute__ ((__dllimport__)) int __attribute__((__cdecl__)) _snwscanf(const wchar_t * __restrict__ _Src,size_t _MaxCount,const wchar_t * __restrict__ _Format,...);
__attribute__ ((__dllimport__)) FILE *__attribute__((__cdecl__)) _wfdopen(int _FileHandle ,const wchar_t *_Mode);
__attribute__ ((__dllimport__)) FILE *__attribute__((__cdecl__)) _wfopen(const wchar_t * __restrict__ _Filename,const wchar_t *__restrict__ _Mode) ;
__attribute__ ((__dllimport__)) FILE *__attribute__((__cdecl__)) _wfreopen(const wchar_t * __restrict__ _Filename,const wchar_t * __restrict__ _Mode,FILE * __restrict__ _OldFile) ;
__attribute__ ((__dllimport__)) void __attribute__((__cdecl__)) _wperror(const wchar_t *_ErrMsg);
__attribute__ ((__dllimport__)) FILE *__attribute__((__cdecl__)) _wpopen(const wchar_t *_Command,const wchar_t *_Mode);
__attribute__ ((__dllimport__)) int __attribute__((__cdecl__)) _wremove(const wchar_t *_Filename);
__attribute__ ((__dllimport__)) wchar_t *__attribute__((__cdecl__)) _wtmpnam(wchar_t *_Buffer);
__attribute__ ((__dllimport__)) wint_t __attribute__((__cdecl__)) _fgetwc_nolock(FILE *_File);
__attribute__ ((__dllimport__)) wint_t __attribute__((__cdecl__)) _fputwc_nolock(wchar_t _Ch,FILE *_File);
__attribute__ ((__dllimport__)) wint_t __attribute__((__cdecl__)) _ungetwc_nolock(wint_t _Ch,FILE *_File);
# 884 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/stdio.h" 3
__attribute__ ((__dllimport__)) void __attribute__((__cdecl__)) _lock_file(FILE *_File);
__attribute__ ((__dllimport__)) void __attribute__((__cdecl__)) _unlock_file(FILE *_File);
__attribute__ ((__dllimport__)) int __attribute__((__cdecl__)) _fclose_nolock(FILE *_File);
__attribute__ ((__dllimport__)) int __attribute__((__cdecl__)) _fflush_nolock(FILE *_File);
__attribute__ ((__dllimport__)) size_t __attribute__((__cdecl__)) _fread_nolock(void * __restrict__ _DstBuf,size_t _ElementSize,size_t _Count,FILE * __restrict__ _File);
__attribute__ ((__dllimport__)) int __attribute__((__cdecl__)) _fseek_nolock(FILE *_File,long _Offset,int _Origin);
__attribute__ ((__dllimport__)) long __attribute__((__cdecl__)) _ftell_nolock(FILE *_File);
__extension__ __attribute__ ((__dllimport__)) int __attribute__((__cdecl__)) _fseeki64_nolock(FILE *_File,long long _Offset,int _Origin);
__extension__ __attribute__ ((__dllimport__)) long long __attribute__((__cdecl__)) _ftelli64_nolock(FILE *_File);
__attribute__ ((__dllimport__)) size_t __attribute__((__cdecl__)) _fwrite_nolock(const void * __restrict__ _DstBuf,size_t _Size,size_t _Count,FILE * __restrict__ _File);
__attribute__ ((__dllimport__)) int __attribute__((__cdecl__)) _ungetc_nolock(int _Ch,FILE *_File);
char *__attribute__((__cdecl__)) tempnam(const char *_Directory,const char *_FilePrefix) ;
int __attribute__((__cdecl__)) fcloseall(void) ;
FILE *__attribute__((__cdecl__)) fdopen(int _FileHandle,const char *_Format) ;
int __attribute__((__cdecl__)) fgetchar(void) ;
int __attribute__((__cdecl__)) fileno(FILE *_File) ;
int __attribute__((__cdecl__)) flushall(void) ;
int __attribute__((__cdecl__)) fputchar(int _Ch) ;
int __attribute__((__cdecl__)) getw(FILE *_File) ;
int __attribute__((__cdecl__)) putw(int _Ch,FILE *_File) ;
int __attribute__((__cdecl__)) rmtmp(void) ;
# 926 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/stdio.h" 3
int __attribute__((__cdecl__)) __mingw_str_wide_utf8 (const wchar_t * const wptr, char **mbptr, size_t * buflen);
# 940 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/stdio.h" 3
int __attribute__((__cdecl__)) __mingw_str_utf8_wide (const char *const mbptr, wchar_t ** wptr, size_t * buflen);
# 949 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/stdio.h" 3
void __attribute__((__cdecl__)) __mingw_str_free(void *ptr);
}
#pragma pack(pop)
# 1 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/sec_api/stdio_s.h" 1 3
# 9 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/sec_api/stdio_s.h" 3
# 1 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/stdio.h" 1 3
# 10 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/sec_api/stdio_s.h" 2 3
# 960 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/stdio.h" 2 3
# 1 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/_mingw_print_pop.h" 1 3
# 962 "D:/LenovoSoftstore/Install/DevC/MinGW64/x86_64-w64-mingw32/include/stdio.h" 2 3
# 43 "D:/LenovoSoftstore/Install/DevC/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++/cstdio" 2 3
# 96 "D:/LenovoSoftstore/Install/DevC/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++/cstdio" 3
namespace std
{
using ::FILE;
using ::fpos_t;
using ::clearerr;
using ::fclose;
using ::feof;
using ::ferror;
using ::fflush;
using ::fgetc;
using ::fgetpos;
using ::fgets;
using ::fopen;
using ::fprintf;
using ::fputc;
using ::fputs;
using ::fread;
using ::freopen;
using ::fscanf;
using ::fseek;
using ::fsetpos;
using ::ftell;
using ::fwrite;
using ::getc;
using ::getchar;
using ::gets;
using ::perror;
using ::printf;
using ::putc;
using ::putchar;
using ::puts;
using ::remove;
using ::rename;
using ::rewind;
using ::scanf;
using ::setbuf;
using ::setvbuf;
using ::sprintf;
using ::sscanf;
using ::tmpfile;
using ::tmpnam;
using ::ungetc;
using ::vfprintf;
using ::vprintf;
using ::vsprintf;
}
# 157 "D:/LenovoSoftstore/Install/DevC/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++/cstdio" 3
namespace __gnu_cxx
{
# 175 "D:/LenovoSoftstore/Install/DevC/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++/cstdio" 3
using ::snprintf;
using ::vfscanf;
using ::vscanf;
using ::vsnprintf;
using ::vsscanf;
}
namespace std
{
using ::__gnu_cxx::snprintf;
using ::__gnu_cxx::vfscanf;
using ::__gnu_cxx::vscanf;
using ::__gnu_cxx::vsnprintf;
using ::__gnu_cxx::vsscanf;
}
# 3 "tmp4.cpp" 2
int a,b;
int main(){
scanf("%d%d",&a,&b);
printf("%d",a+b);
return 0;
}
发现代码长达 41KB,917 行,然后我们打开来一看,惊奇地发现里面的东西还符合 g++ 的语法,并且如果你尝试用 g++ 编译生成的 .i
文件,你会发现还是可以得到可执行文件。这告诉我们,预编译无非只是做了以下几件事,并没有完全改变代码的内容:
- 展开 define
- 展开所有 include
- 删除所有注释
- 处理所有
#ifdef
和#endif
- 添加行号和文件标识符
- 保留
#pragma
编译器指令,在后面编译阶段使用。
接下来,我们执行 g++ tmp4.cpp -S
,然后打开 tmp4.s
,发现里面是用汇编语言写成的代码
.file "tmp4.cpp"
.section .text$_Z5scanfPKcz,"x"
.linkonce discard
.globl _Z5scanfPKcz
.def _Z5scanfPKcz; .scl 2; .type 32; .endef
.seh_proc _Z5scanfPKcz
_Z5scanfPKcz:
.LFB2:
pushq %rbp
.seh_pushreg %rbp
pushq %rbx
.seh_pushreg %rbx
subq $56, %rsp
.seh_stackalloc 56
leaq 128(%rsp), %rbp
.seh_setframe %rbp, 128
.seh_endprologue
movq %rdx, -40(%rbp)
movq %r8, -32(%rbp)
movq %r9, -24(%rbp)
movq %rcx, -48(%rbp)
leaq -40(%rbp), %rax
movq %rax, -88(%rbp)
movq -88(%rbp), %rax
movq %rax, %rdx
movq -48(%rbp), %rcx
call __mingw_vscanf
movl %eax, %ebx
movl %ebx, %eax
addq $56, %rsp
popq %rbx
popq %rbp
ret
.seh_endproc
.section .text$_Z6printfPKcz,"x"
.linkonce discard
.globl _Z6printfPKcz
.def _Z6printfPKcz; .scl 2; .type 32; .endef
.seh_proc _Z6printfPKcz
_Z6printfPKcz:
.LFB8:
pushq %rbp
.seh_pushreg %rbp
pushq %rbx
.seh_pushreg %rbx
subq $56, %rsp
.seh_stackalloc 56
leaq 128(%rsp), %rbp
.seh_setframe %rbp, 128
.seh_endprologue
movq %rdx, -40(%rbp)
movq %r8, -32(%rbp)
movq %r9, -24(%rbp)
movq %rcx, -48(%rbp)
leaq -40(%rbp), %rax
movq %rax, -88(%rbp)
movq -88(%rbp), %rax
movq %rax, %rdx
movq -48(%rbp), %rcx
call __mingw_vprintf
movl %eax, %ebx
movl %ebx, %eax
addq $56, %rsp
popq %rbx
popq %rbp
ret
.seh_endproc
.globl a
.bss
.align 4
a:
.space 4
.globl b
.align 4
b:
.space 4
.def __main; .scl 2; .type 32; .endef
.section .rdata,"dr"
.LC0:
.ascii "%d%d\0"
.LC1:
.ascii "%d\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
.LFB31:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
call __main
leaq b(%rip), %r8
leaq a(%rip), %rdx
leaq .LC0(%rip), %rcx
call _Z5scanfPKcz
movl a(%rip), %edx
movl b(%rip), %eax
addl %edx, %eax
movl %eax, %edx
leaq .LC1(%rip), %rcx
call _Z6printfPKcz
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (tdm64-1) 4.9.2"
.def __mingw_vscanf; .scl 2; .type 32; .endef
.def __mingw_vprintf; .scl 2; .type 32; .endef
显然,此时得到的是经过编译得到的汇编代码。g++ 形成的汇编代码中包含一些无用信息,所有以 .
开头的行都是在给汇编器和链接器下达命令,称为“汇编器命令”。
接下来我们执行 g++ -c tmp4.cpp
,然后打开得到得到的 tmp4.o
,如果你用记事本/devc++ 打开的话会发现一堆乱码,这里我们用 sublime 打开,发现有:
6486 0d00 0000 0000 4c04 0000 2500 0000
0000 0400 2e74 6578 7400 0000 0000 0000
0000 0000 5000 0000 1c02 0000 8403 0000
0000 0000 0900 0000 2000 5060 2e64 6174
6100 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
4000 50c0 2e62 7373 0000 0000 0000 0000
0000 0000 1000 0000 0000 0000 0000 0000
0000 0000 0000 0000 8000 50c0 2f34 0000
0000 0000 0000 0000 0000 0000 5000 0000
6c02 0000 de03 0000 0000 0000 0100 0000
2010 5060 2f32 3300 0000 0000 0000 0000
0000 0000 0c00 0000 bc02 0000 0000 0000
0000 0000 0000 0000 4010 3040 2f34 3300
0000 0000 0000 0000 0000 0000 0c00 0000
c802 0000 e803 0000 0000 0000 0300 0000
4010 3040 2f36 3300 0000 0000 0000 0000
0000 0000 5000 0000 d402 0000 0604 0000
0000 0000 0100 0000 2010 5060 2f38 3300
0000 0000 0000 0000 0000 0000 0c00 0000
2403 0000 0000 0000 0000 0000 0000 0000
4010 3040 2f31 3034 0000 0000 0000 0000
0000 0000 0c00 0000 3003 0000 1004 0000
0000 0000 0300 0000 4010 3040 2e72 6461
7461 0000 0000 0000 0000 0000 1000 0000
3c03 0000 0000 0000 0000 0000 0000 0000
4000 5040 2e78 6461 7461 0000 0000 0000
0000 0000 0c00 0000 4c03 0000 0000 0000
0000 0000 0000 0000 4000 3040 2e70 6461
7461 0000 0000 0000 0000 0000 0c00 0000
5803 0000 2e04 0000 0000 0000 0300 0000
4000 3040 2f31 3235 0000 0000 0000 0000
0000 0000 2000 0000 6403 0000 0000 0000
0000 0000 0000 0000 4000 5040 5548 89e5
4883 ec20 e800 0000 004c 8d05 0400 0000
488d 1500 0000 0048 8d0d 0000 0000 e800
0000 008b 1500 0000 008b 0504 0000 0001
d089 c248 8d0d 0500 0000 e800 0000 00b8
0000 0000 4883 c420 5dc3 9090 5553 4883
ec38 488d ac24 8000 0000 4889 55d8 4c89
45e0 4c89 4de8 4889 4dd0 488d 45d8 4889
45a8 488b 45a8 4889 c248 8b4d d0e8 0000
0000 89c3 89d8 4883 c438 5b5d c390 9090
9090 9090 9090 9090 9090 9090 010e 0485
0e03 0662 0230 0150 0000 0000 4100 0000
0000 0000 5553 4883 ec38 488d ac24 8000
0000 4889 55d8 4c89 45e0 4c89 4de8 4889
4dd0 488d 45d8 4889 45a8 488b 45a8 4889
c248 8b4d d0e8 0000 0000 89c3 89d8 4883
c438 5b5d c390 9090 9090 9090 9090 9090
9090 9090 010e 0485 0e03 0662 0230 0150
0000 0000 4100 0000 0000 0000 2564 2564
0025 6400 0000 0000 0000 0000 0108 0305
0832 0403 0150 0000 0000 0000 4e00 0000
0000 0000 4743 433a 2028 7464 6d36 342d
3129 2034 2e39 2e32 0000 0000 0000 0000
0000 0000 0900 0000 2200 0000 0400 1000
0000 0e00 0000 0400 1700 0000 0e00 0000
0400 1e00 0000 1800 0000 0400 2300 0000
0400 0000 0400 2900 0000 0e00 0000 0400
2f00 0000 0e00 0000 0400 3a00 0000 1800
0000 0400 3f00 0000 0800 0000 0400 3200
0000 2300 0000 0400 0000 0000 0200 0000
0300 0400 0000 0200 0000 0300 0800 0000
1000 0000 0300 3200 0000 2400 0000 0400
0000 0000 0600 0000 0300 0400 0000 0600
0000 0300 0800 0000 1400 0000 0300 0000
0000 0a00 0000 0300 0400 0000 0a00 0000
0300 0800 0000 1a00 0000 0300 2e66 696c
6500 0000 0000 0000 feff 0000 6701 746d
7034 2e63 7070 0000 0000 0000 0000 0000
0000 0000 8800 0000 0000 0000 0400 0000
0301 4100 0000 0100 0000 0000 0000 0000
0200 0000 0000 0000 9b00 0000 0000 0000
0400 2000 0201 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 a800 0000
0000 0000 0700 0000 0301 4100 0000 0100
0000 0000 0000 0000 0200 0000 0000 0000
bc00 0000 0000 0000 0700 2000 0200 6d61
696e 0000 0000 0000 0000 0100 2000 0200
2e74 6578 7400 0000 0000 0000 0100 0000
0301 4e00 0000 0900 0000 0000 0000 0000
0000 0000 2e64 6174 6100 0000 0000 0000
0200 0000 0301 0000 0000 0000 0000 0000
0000 0000 0000 0000 2e62 7373 0000 0000
0000 0000 0300 0000 0301 0800 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
ca00 0000 0000 0000 0500 0000 0301 0c00
0000 0000 0000 0000 0000 0000 0200 0000
0000 0000 de00 0000 0000 0000 0600 0000
0301 0c00 0000 0300 0000 0000 0000 0000
0200 0000 0000 0000 f200 0000 0000 0000
0800 0000 0301 0c00 0000 0000 0000 0000
0000 0000 0200 0000 0000 0000 0701 0000
0000 0000 0900 0000 0301 0c00 0000 0300
0000 0000 0000 0000 0200 0000 2e72 6461
7461 0000 0000 0000 0a00 0000 0301 0800
0000 0000 0000 0000 0000 0000 0000 0000
2e78 6461 7461 0000 0000 0000 0b00 0000
0301 0c00 0000 0000 0000 0000 0000 0000
0000 0000 2e70 6461 7461 0000 0000 0000
0c00 0000 0301 0c00 0000 0300 0000 0000
0000 0000 0000 0000 0000 0000 1c01 0000
0000 0000 0d00 0000 0301 1500 0000 0000
0000 0000 0000 0000 0000 0000 6100 0000
0000 0000 0000 0000 0300 0000 0200 6200
0000 0000 0000 0400 0000 0300 0000 0200
5f5f 6d61 696e 0000 0000 0000 0000 2000
0200 0000 0000 2701 0000 0000 0000 0000
2000 0200 0000 0000 3601 0000 0000 0000
0000 2000 0200 4601 0000 2e74 6578 7424
5f5a 3573 6361 6e66 504b 637a 002e 7864
6174 6124 5f5a 3573 6361 6e66 504b 637a
002e 7064 6174 6124 5f5a 3573 6361 6e66
504b 637a 002e 7465 7874 245f 5a36 7072
696e 7466 504b 637a 002e 7864 6174 6124
5f5a 3670 7269 6e74 6650 4b63 7a00 2e70
6461 7461 245f 5a36 7072 696e 7466 504b
637a 002e 7264 6174 6124 7a7a 7a00 2e74
6578 7424 5f5a 3573 6361 6e66 504b 637a
005f 5a35 7363 616e 6650 4b63 7a00 2e74
6578 7424 5f5a 3670 7269 6e74 6650 4b63
7a00 5f5a 3670 7269 6e74 6650 4b63 7a00
2e78 6461 7461 245f 5a35 7363 616e 6650
4b63 7a00 2e70 6461 7461 245f 5a35 7363
616e 6650 4b63 7a00 2e78 6461 7461 245f
5a36 7072 696e 7466 504b 637a 002e 7064
6174 6124 5f5a 3670 7269 6e74 6650 4b63
7a00 2e72 6461 7461 247a 7a7a 005f 5f6d
696e 6777 5f76 7363 616e 6600 5f5f 6d69
6e67 775f 7670 7269 6e74 6600
很显然,这时候编译得到的东西就不是人能看得懂的代码,而是能够被机器直接读取的二进制文件了,这时候得到的就是目标文件。
最后就是我们最常用的 g++ a.cpp -o a.exe
了,此命令能够实现预编译、编译、汇编、链接四键合一。
这里推荐一个专门可以查看汇编代码的网站:https://gcc.godbolt.org/
讲个笑话:这东西甚至可以卡常数!
https://codeforces.com/contest/1270/submission/149785206 是不是比上周五那发快一点……
具体方法就是:对于 windows 下评测的 OJ,把得到的汇编代码复制一遍,然后 __asm__(R"([换行符][在这里粘上你的 .s文件])")
即可。只要别作死在比赛中用就没事……
编译选项 -E/-o/-c/-S
聊完了,接下来讲讲编译开关的事情,OIers 常用的编译开关有以下几个:
-O2
表示开启 O2 优化,-O3
,-Ofast
也同理-std=c++11
按 C++11 的标准来编译程序。目前 NOIp 所用的开关都是-std=c++14
。-g
,在编译的时产生调试信息。-lm
动态链接时将连接 GCC 的标准数学库libm.a
(不过这个开关 g++ 默认是开着的),同理-lc
表示连接 GCC 的标准 C 库libc.a
,-lgcc
表示连接 GCC 的标准支持库libgcc.a
。-Wall
编译时显示最多调试信息。-Wl,--stack=2147483648
将递归栈开到 \(2147483648\) 个字节。-Dmacro
,等价于在程序中加入#define macro
,譬如DONLINE_JUDGE
就等价于#define ONLINE_JUDGE
。
最后一部分就是 DOS 的快捷键了。众所周知,devc++ 编译出来的程序并不是你写的程序,而是系统调用了一个名叫 ConsolePauser.exe
的程序,然后把你写的代码放进去执行。而 ConsolePauser 的界面就是 DOS 的界面,因此掌握一些 DOS 快捷键有关的知识还是有必要的:
- Ctrl+Z:输入 EOF 字符(在 Linux 底下是 Ctrl+D,当年 THUSC 时 D1T4 的 grader 用了
fread
,然后我就倒腾了一年 THUWC 下的 EOF 是啥。。。。。。) - Ctrl+C:关闭窗口/结束进程,不是复制!
- Ctrl+A:全选,这和一般的文本编辑器是一样的。
- Ctrl+V:粘贴,也和一般的文本编辑器是一样的。
- Ctrl+H:backspace。
- 选中一部分后 Enter:复制。
3. C++ & Dev-C++
首先先做一个 clarification:C++、G++、DevC++ 三者之间的区别,相信有很多初学者和我这个老年菜鸡一样分不清这三者之间的区别。C++ 是一门计算机语言,而 G++、DevC++ 均不是语言,G++ 是一款编译器中编译 C++ 程序的命令。之所以在有的 OJ 上,C++ 和 G++ 都作为一种编译语言出现,是因为它们编译方式不同,C++ 即 ANSI C++ 是按照最标准的编译方式进行编译,而 G++ 即 GNU C++ 则是 GNU 项目中最平凡适用人群最多的编译器编译(Windows 下是 MinGW GCC),二者之间存在微小差异,譬如在 ANSI C++ 中,++x
与 x++
效率差别较大,而在 GNU C++ 中,二者效率差异并不是很大。ANSI C++、GNU C++、Clang 是并列的 C++ 语言的编译器,而所谓 C++11、C++14、C++17 是不同的编译标准(即编译开关 std=c++11/14/17
)。
而 Dev-C++ 是一种 IDE,即集成开发环境,支持对 C/C++ 语言代码编写功能、分析功能、编译功能、调试功能等一体化、一键化,也具备图形页面与代码编辑器、调试器与编译器,除了 Dev-C++ 之外,Visual Studio、Eclipse(Java)、PyCharm、Xcode(在 MacOS 上)均为 IDE。
然后讲一个 Dev 的冷知识:Dev 给出的三个编译器(release、debug、profiling)的区别:
- release 一般表示发行版,其没有调试功能,也没有性能分析功能,一般开发商发布的软件都是用 release 编译的。
- debug 表示调试版,除了 debug 编译器之外,其余两者都没有按 F5 调试的功能(不信自己去试一试)
- profiling 表示性能分析版,除了 profiling 编译器之外,其余两者都没有性能分析的功能(不信自己去试一试)
OIer 需要直到的电脑知识大概就这么多,总而言之是什么用得习惯就用什么,必要的计算机知识还是要懂一些。