GCC筆記 命令行分析

1984年,Richard Stallman發起了自由軟件運動,GNU (Gnu's Not Unix)項目應運而生,3年后,最初版的GCC橫空出世,成為第一款可移植、可優化、支持ANSI C的開源C編譯器。
GCC最初的全名是GNU C Compiler,之后,隨著GCC支持的語言越來越多,它的名稱變成了GNU Compiler Collection。
這里介紹的gcc是GCC的前端,C編譯器.


警告信息


-Wall : 顯示所有常用的編譯警告信息。
?? ?-W??? : 顯示更多的常用編譯警告,如:變量未使用、一些邏輯錯誤。
?? ?-Wconversion : 警告隱式類型轉換。
?? ?-Wshadow : 警告影子變量(在代碼塊中再次聲明已聲明的變量)
?? ?-Wcast-qual :警告指針修改了變量的修飾符。如:指針修改const變量。
?? ?-Wwrite-strings : 警告修改const字符串。
?? ?-Wtraditional : 警告ANSI編譯器與傳統C編譯器有不同的解釋。
?? ?-Werror : 即使只有警告信息,也不編譯。(gcc默認:若只有警告信息,則進行編譯,若有錯誤信息,則不編譯)


C語言標準


你可以在gcc的命令行中通過指定選項來選擇相應的C語言標準: 從傳統c到最新的GNU擴展C. 默認情況下, gcc使用最新的GNU C擴展.

?? ?-ansi : 關閉GNU擴展中與ANSI C相抵觸的部分。
?? ?-pedantic????????? : 關閉所有的GNU擴展。
?? ?-std=c89?????????? : 遵循C89標準
?? ?-std=c99?????????? : 遵循C99標準
??? -std=traditional : 使用原始C
注意:后4個選項可以與-ansi結合使用,也可以單獨使用。

可在gcc中使用大量GNU C擴展.

生成特定格式的文件


以hello.c為例子,可以設置選項生成hello.i, hello.s, hello.o以及最終的hello文件:

?? ?hello.c : 最初的源代碼文件;
?? ?hello.i : 經過編譯預處理的源代碼;
?? ?hello.s : 匯編處理后的匯編代碼;
?? ?hello.o : 編譯后的目標文件,即含有最終編譯出的機器碼,但它里面所引用的其他文件中函數的內存位置尚未定義。
??? hello / a.out : 最終的可執行文件
??? (還有.a(靜態庫文件), .so(動態庫文件), .s(匯編源文件)留待以后討論)

如果你不通過-o指定生成可執行文件名,那么會默認生成a.out. 不指定生成文件名肯能覆蓋你上次生成的a.out.

e.g.
$ gcc hello.c
在不給gcc傳遞任何參數的情況下, gcc執行默認的操作: 將源文件編譯為目標文件--> 將目標文件連接為可執行文件(名為a.out) --> 刪除目標文件.

-c生成.o文件時,默認生成與源代碼的主干同名的.o文件。比如對應hello.c生成hello.o. 但也可在生成目標文件時指定目標文件名(注意同時要給出.o后綴): $gcc -c -o demo.o demo.c

??? $ gcc -Wall -c hello.c????????????? : 生成hello.o
?? ?$ gcc -Wall -c -save-temps hello.c? : 生成hello.i, hello.s, hello.o
?? ?注意-Wall 選項的使用場合:僅在涉及到編譯(即會生成.o文件時,用-Wall)??

多文件編譯、連接


如果原文件分布于多個文件中:file1.c, file2,c
?? ?$ gcc -Wall file1.c file2.c -o name

若對其中一個文件作了修改,則可只重新編譯該文件,再連接所有文件:
?? ?$ gcc -Wall -c file2.c
?? ?$ gcc file1.c file2.o -c name

注意:若編譯器在命令行中從左向右順序讀取.o文件,則它們的出現順序有限制:含有某函數定義的文件必須出現在含有調用該函數的文件之后。好在GCC無此限制。

編譯預處理


以上述的hello.c為例, 要對它進行編譯預備處理, 有兩種方法: 在gcc中指定-E選項, 或直接調用cpp.gcc的編譯預處理命令程序為cpp,比較新版本的gcc已經將cpp集成了,但仍提供了cpp命令. 可以直接調用cpp命令, 也可以在gcc中指定-E選項指定它只進行編譯預處理.

$ gcc -E hello.c??????????????????????????? ==? $ cpp hello.c
上述命令馬上將預處理結果顯示出來. 不利于觀看. 可采用-c將預處理結果保存:
$ gcc -E -c hello.i hello.c????????????? ==? $ cpp -o hello.i hello.c
注意, -c指定名稱要給出".i"后綴.

另外, gcc針對編譯預處理提供了一些選項:
(1) 除了直接在源代碼中用 #define NAME來定義宏外,gcc可在命令行中定義宏:-DNAME(其中NAME為宏名),? 也可對宏賦值: -DNAME=value 注意等號兩邊不能有空格! 由于宏擴展只是一個替換過程,也可以將value換成表達式,但要在兩邊加上雙括號: -DNAME="statement"
e.g. $ gcc -Wall -DVALUE="2+2" tmp.c -o tmp
如果不顯示地賦值,如上例子,只給出:-DVALUE,gcc將使用默認值:1.

(2) 除了用戶定義的宏外, 有一些宏是編譯器自動定義的,它們以__開頭,運行: $ cpp -dM /dev/null, 可以看到這些宏. 注意, 其中含有不以__開頭的非ANSI宏,它們可以通過-ansi選項被禁止。
?
查看宏擴展

1, 運行 $ gcc -E test.c ,gcc對test.c進行編譯預處理,并立馬顯示結果. (不執行編譯) 2, 運行 $gcc -c -save-temps test.c ,不光產生test.o,還產生test.i, test.s,前者是編譯預處理結果, 后者是匯編結果.
???
利用Emacs查看編譯預處理結果

針對含有編譯預處理命令的代碼,可以利用emacs方便地查看預處理結果,而不需執行編譯,更為方便的是,可以只選取一段代碼,而非整個文件:
1,選擇想要查看的代碼
2,C-c C-e (M-x c-macro-expand)
這樣,就自動在一個名為"Macroexpansion"的buffer中顯示pre-processed結果.

生成匯編代碼


使用"-S"選項指定gcc生成以".s"為后綴的匯編代碼:
$ gcc -S hello.c
$ gcc -S -o hello.s hello.c

生成匯編語言的格式取決于目標平臺. 另外, 如果是多個.c文件, 那么針對每一個.c文件生成一個.s文件.

包含頭文件在程序中包含與連接庫對應的頭文件是很重要的方面,要使用庫,就一定要能正確地引用頭文件。一般在代碼中通過#include引入頭文件, 如果頭文件位于系統默認的包含路徑(/usr/includes), 則只需在#include中給出頭文件的名字, 不需指定完整路徑.? 但若要包含的頭文件位于系統默認包含路徑之外, 則有其它的工作要做: 可以(在源文件中)同時指定頭文件的全路徑. 但考慮到可移植性,最好通過-I在調用gcc的編譯命令中指定。


?

?

?

下面看這個求立方的小程序(陰影語句表示剛開始不存在):

#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[])
{
? double x = pow (2.0, 3.0);
? printf("The cube of 2.0 is %f/n", x);
? return 0;
}

使用gcc-2.95來編譯它(-lm選項在后面的連接選項中有介紹, 這里只討論頭文件的包含問題):
$ gcc-2.95 -Wall pow.c -lm -o pow_2.95
pow.c: In function `main':
pow.c:5: warning: implicit declaration of function `pow'

程序編譯成功,但gcc給出警告: pow函數隱式聲明。
$ ./pow_2.95
The cube of 2.0 is 1.000000

明顯執行結果是錯誤的,在源程序中引入頭文件(#include <math.h>),消除了錯誤。

不要忽略Warning信息!它可能預示著,程序雖然編譯成功,但運行結果可能有錯。故,起碼加上"-Wall"編譯選項!并盡量修正Warning警告。

搜索路徑

首先要理解 #include<file.h>和#include"file.h"的區別:
#include<file.h>只在默認的系統包含路徑搜索頭文件
#include"file.h"首先在當前目錄搜索頭文件, 若頭文件不位于當前目錄, 則到系統默認的包含路徑搜索頭文件.

UNIX類系統默認的系統路徑為:

頭文件,包含路徑: /usr/local/include/? or? /usr/include/
庫文件,連接路徑: /usr/local/lib/????????? or? /usr/lib/???

對于標準c庫(glibc或其它c庫)的頭文件, 我們可以直接在源文件中使用#include <file.h>來引入頭文件.

如果要在源文件中引入自己的頭文件, 就需要考慮下面的問題:

1, 如果使用非系統頭文件, 頭文件和源文件位于同一個目錄, 如何引用頭文件呢?
——我們可以簡單地在源文件中使用 #include "file.h", gcc將當前目錄的file.h引入到源文件. 如果你很固執, 仍想使用#include <file.h>語句, 可以在調用gcc時添加"-I."來將當前目錄添加到系統包含路徑. 細心的朋友可能會想到: 這樣對引用其它頭文件會不會有影響? 比如, #include<file.h>之后緊接著一個#include<math.h>, 它能正確引入math.h嗎? 答案是: 沒有影響. 仍然能正確引用math.h. 我的理解是: "-I."將當前目錄作為包含路徑的第一選擇, 若在當前目錄找不到頭文件, 則在默認路徑搜索頭文件. 這實際上和#include"file.h"是一個意思.

2, 對于比較大型的工程, 會有許多用戶自定義的頭文件, 并且頭文件和.c文件會位于不同的目錄. 又該如何在.c文件中引用頭文件呢?
—— 可以直接在.c文件中利用#include“/path/file.h", 通過指定頭文件的路徑(可以是絕對路徑, 也可以是相對路徑)來包含頭文件. 但這明顯降低了程序的可移植性. 在別的系統環境下編譯可能會出現問題. 所以還是利用"-I"選項指定頭文件完整的包含路徑.

針對頭文件比較多的情況, 最好把它們統一放在一個目錄中, 比如~/project/include. 這樣就不需為不同的頭文件指定不同的路徑. 如果你嫌每次輸入這么多選項太麻煩, 你可以通過設置環境變量來添加路徑:
$ C_INCLUDE_PATH=/opt/gdbm-1.8.3/include
$ export C_INCLUDE_PATH
$ LIBRART_PATH=/opt/gdbm-1.8.3/lib
$ export LIBRART_PATH

可一次指定多個搜索路徑,":"用于分隔它們,"."表示當前路徑,如:
$ C_INCLUDE_PATH=.:/opt/gdbm-1.8.3/include:/net/include
$ LIBRARY_PATH=.:/opt/gdbm-1.8.3/lib:/net/lib
(可以添加多個路徑,路徑之間用:相隔,.代表當前目錄,若.在最前頭,也可省略)

當然,若想永久地添加這些路徑,可以在.bash_profile中添加上述語句.

3, 還有一個比較猥瑣的辦法: 系統默認的包含路徑不是/usr/include或/usr/local/include么? 我把自己的頭文件拷貝到其中的一個目錄, 不就可以了么? 的確可以這樣, 如果你只想在你自己的機器上編譯運行這個程序的話.

前面介紹了三種添加搜索路徑的方法,如果這三種方法一起使用,優先級如何呢?
命令行設置 > 環境變量設置 > 系統默認

與外部庫連接


前面介紹了如何包含頭文件. 而頭文件和庫是息息相關的, 使用庫時, 要在源代碼中包含適當的頭文件,這樣才能聲明庫中函數的原型(發布庫時, 就需要給出相應的頭文件).

和包含路徑一樣, 系統也有默認的連接路徑:
頭文件,包含路徑: /usr/local/include/? or? /usr/include/
庫文件,連接路徑: /usr/local/lib/????????? or? /usr/lib/??

同樣地, 我們想要使用某個庫里的函數, 必須將這個庫連接到使用那些函數的程序中.

有一個例外: libc.a或libc.so (C標準庫,它包含了ANSI C所定義的C函數)是不需要你顯式連接的, 所有的C程序在運行時都會自動加載c標準庫.

除了C標準庫之外的庫稱之為"外部庫", 它可能是別人提供給你的, 也可能是你自己創建的(后面有介紹如何創建庫的內容).

外部庫有兩種:(1)靜態連接庫lib.a
???????????????????? (2)共享連接庫lib.so

兩者的共同點:
??? .a, .so都是.o目標文件的集合,這些目標文件中含有一些函數的定義(機器碼),而這些函數將在連接時會被最終的可執行文件用到。

兩者的區別:
?? ?靜態庫.a? : 當程序與靜態庫連接時,庫中目標文件所含的所有將被程序使用的函數的機器碼被copy到最終的可執行文件中. 靜態庫有個缺點: 占用磁盤和內存空間. 靜態庫會被添加到和它連接的每個程序中, 而且這些程序運行時, 都會被加載到內存中. 無形中又多消耗了更多的內存空間.

??? 共享庫.so : 與共享庫連接的可執行文件只包含它需要的函數的引用表,而不是所有的函數代碼,只有在程序執行時, 那些需要的函數代碼才被拷貝到內存中, 這樣就使可執行文件比較小, 節省磁盤空間(更進一步,操作系統使用虛擬內存,使得一份共享庫駐留在內存中被多個程序使用).共享庫還有個優點: 若庫本身被更新, 不需要重新編譯與它連接的源程序。

靜態庫

下面我們來看一個簡單的例子,計算2.0的平方根(假設文件名為sqrt.c):

#include <math.h>
#include <stdio.h>
int
main (void)
{
double x = sqrt (2.0);
printf ("The square root of 2.0 is %f/n", x);
return 0;
}

用gcc將它編譯為可執行文件:
$ gcc -Wall sqrt.c -o sqrt
編譯成功,沒有任何警告或錯誤信息。執行結果也正確。
$ ./sqrt
The square root of 2.0 is 1.414214
????
下面我們來看看剛才使用的gcc版本:
$ gcc --version
??gcc (GCC) 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)

現在我用2.95版的gcc把sqrt.c再編譯一次:
$ gcc-2.95 -Wall sqrt.c -o sqrt_2.95
??/tmp/ccVBJd2H.o: In function `main':
??sqrt.c:(.text+0x16): undefined reference to `sqrt'
???? collect2: ld returned 1 exit status
????
編譯器會給出上述錯誤信息,這是因為sqrt函數不能與外部數學庫"libm.a"相連。sqrt函數沒有在程序中定義,也不存在于默認C庫 "libc.a"中,如果用gcc-2.95,應該顯式地選擇連接庫。上述出錯信息中的"/tmp/ccVBJd2H.o"是gcc創造的臨時目標文件,用作連接時用。

使用下列的命令可以成功編譯:
$ gcc-2.95 -Wall sqrt.c /usr/lib/libm.a -o sqrt_2.95
它告知gcc:在編譯sqrt.c時,加入位于/usr/lib中的libm.a庫(C數學庫)。

C庫文件默認位于/usr/lib, /usr/local/lib系統目錄中; gcc默認地從/usr/local/lib, /usr/lib中搜索庫文件。(在我的Ubuntu系統中,C庫文件位于/urs/lib中。

這里還要注意連接順序的問題,比如上述命令,如果我改成:
$ gcc-2.95 -Wall /usr/lib/libm.asqrt.c -o sqrt_2.95
gcc會給出出錯信息:
?/tmp/cc6b3bIa.o: In function `main':
?sqrt.c:(.text+0x16): undefined reference to `sqrt'
?collect2: ld returned 1 exit status

正如讀取目標文件的順序,gcc也在命令行中從左向右讀取庫文件——任何包含某函數定義的庫文件必須位于調用該函數的目標文件之后!

指定庫文件的絕對路徑比較繁瑣,有一種簡化方法,相對于上述命令,可以用下面的命令來替代:
$ gcc-2.95 -Wall sqrt.c -lm -o sqrt_2.95
其中的"-l"表示與庫文件連接,"m"代表"libm.a"中的m。一般而言,"-lNAME"選項會使gcc將目標文件與名為"libNAME.a"的庫文件相連。(這里假設使用默認目錄中的庫,對于其他目錄中的庫文件,參考后面的“搜索路徑”。)

上面所提到的"libm.a"就是靜態庫文件,所有靜態庫文件的擴展名都是.a!
$ whereis libm.a
??libm: /usr/lib/libm.a /usr/lib/libm.so

正如前面所說,默認的庫文件位于/usr/lib/或/usr/local/lib/目錄中。其中,libm.a是靜態庫文件,libm.so是后面會介紹的動態共享庫文件。

如果調用的函數都包含在libc.a中(C標準庫被包含在/usr/lib/libc.a中,它包含了ANSI C所定義的C函數)。那么沒有必要顯式指定libc.a:所有的C程序運行時都自動包含了C標準庫!(試試 $ gcc-2.95 -Wall hello.c -o hello)。

共享庫

正因為共享庫的優點,如果系統中存在.so庫,gcc默認使用共享庫(在/usr/lib/目錄中,庫文件以共享和靜態兩種版本存在)。?

運行:$ gcc -Wall -L. hello.c -lNAME -o hello
gcc先檢查是否有替代的libNAME.so庫可用。???

正如前面所說,共享庫以.so為擴展名(so == shared object)。

那么,如果不想用共享庫,而只用靜態庫呢?可以加上 -static選項
$ gcc -Wall -static hello.c -lNAME -o hello
它等價于:
$ gcc -Wall hello.c libNAME.a -o hello

$ gcc-2.95 -Wall sqrt.c -static -lm -o sqrt_2.95_static
$ gcc-2.95 -Wall sqrt.c -lm -o sqrt_2.95_default
$ gcc-2.95 -Wall sqrt.c /usr/lib/libm.a -o sqrt_2.95_a
$ gcc-2.95 -Wall sqrt.c /usr/lib/libm.so -o sqrt_2.95_so

$ ls -l sqrt*
-rwxr-xr-x? 1 zp zp? 21076 2006-04-25 14:52 sqrt_2.95_a
-rwxr-xr-x? 1 zp zp?? 7604 2006-04-25 14:52 sqrt_2.95_default
-rwxr-xr-x? 1 zp zp?? 7604 2006-04-25 14:52 sqrt_2.95_so
-rwxr-xr-x? 1 zp zp 487393 2006-04-25 14:52 sqrt_2.95_static

上述用四種方式編譯sqrt.c,并比較了可執行文件的大小。奇怪的是,-static -lm 和 /lib/libm.a為什么有區別?有知其原因著,懇請指明,在此謝謝了! :)

如果libNAME.a在當前目錄,應執行下面的命令:
$ gcc -Wall -L. hello.c -lNAME -o hello
-L.表示將當前目錄加到連接路徑。

利用GNU archiver創建庫

$ ar cr libhello.a hello_fn.o by_fn.o
從hello_fn.o和by_fn.o創建libihello.a,其中cr表示:creat & replace
$ ar t libhello.a
列出libhello.a中的內容,t == table
(也可創建libhello.so)

關于創建庫的詳細介紹,可參考本blog的GNU binutils筆記


調試

?


一般地,可執行文件中是不包含任何對源代碼的參考的,而debugger要工作,就要知道目標文件/可執行文件中的機器碼對應的源代碼的信息(如:哪條語句、函數名、變量名...). debugger工作原理:將函數名、變量名,對它們的引用,將所有這些對象對應的代碼行號儲存到目標文件或可執行文件的符號表中。

?

GCC提供-g選項,將調試信息加入到目標文件或可執行文件中。
$ gcc -Wall -g hello.c -o hello

注意:若發生了段錯誤,但沒有core dump,是由于系統禁止core文件的生成!
$ ulimit -c  ,若顯示為0,則系統禁止了core dump

解決方法:
$ ulimit -c unlimited  (只對當前shell進程有效)
或在~/.bashrc 的最后加入: ulimit -c unlimited (一勞永逸)

優化


GCC具有優化代碼的功能,代碼的優化是一項比較復雜的工作,它可歸為:源代碼級優化、速度與空間的權衡、執行代碼的調度。

?

GCC提供了下列優化選項:
??? -O0? : 默認不優化(若要生成調試信息,最好不優化)
??? -O1? : 簡單優化,不進行速度與空間的權衡優化;???
??? -O2? : 進一步的優化,包括了調度。(若要優化,該選項最適合,它是GNU發布軟件的默認優化級別;
??? -O3? : 雞肋,興許使程序速度更慢;
??? -funroll-loops? : 展開循環,會使可執行文件增大,而速度是否增加取決于特定環境;
??? -Os? : 生成最小執行文件;

一般來說,調試時不優化,一般的優化選項用-O2(gcc允許-g與-O2聯用,這也是GNU軟件包發布的默認選項),embedded可以考慮-Os。

注意:此處為O!(非0或小寫的o,-o是指定可執行文件名)。

檢驗優化結果的方法:$ time ./prog

time測量指定程序的執行時間,結果由三部分組成:
??? real : 進程總的執行時間, 它和系統負載有關(包括了進程調度,切換的時間)
??? user: 被測量進程中用戶指令的執行時間
??? sys? : 被測量進程中內核代用戶指令執行的時間

user和sys的和被稱為CPU時間.

注意:對代碼的優化可能會引發警告信息,移出警告的辦法不是關閉優化,而是調整代碼。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/454851.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454851.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454851.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java 反射用法_Java 反射的概念與使用

一&#xff0c;反射的概念對于一個人來說&#xff0c;了解自己的能力、本事、特點&#xff0c;對于他去干事創業來說&#xff0c;是很重要的。同樣的&#xff0c;對于一門面向對象的語言來說&#xff0c;了解類(對象其實就是類的實現)本身也是重要的&#xff0c;可以在很多地方…

關于Unity中的Mesh Collider碰撞器

原來我的場景中有一個平面Plane帶Mesh Collider碰撞器組件&#xff0c;一個主角Hero帶有一個Box Collider碰撞器和有重力的Rigidbody剛體組件&#xff0c;主角可以放在平面上。 在導入場景后&#xff0c;隱藏平面Plane&#xff0c;給一個地板添加一個Mesh Collider碰撞器&#…

GCC常用選項使用詳解

通常所說的GCC是GUN Compiler Collection的簡稱&#xff0c;除了編譯程序之外&#xff0c;它還含其他相關工具&#xff0c;所以它能把易于人類使用的高級語言編寫的源代碼構建成計算機能夠直接執行的二進制代碼。GCC是Linux平臺下最常用的編譯程序&#xff0c;它是Linux平臺編譯…

java 井字棋 人機_井字游戲 人機對戰 java實現

package com.ecnu.Main;/*** 主函數觸發游戲*/public class MainApplication {public static void main(String[] args){TicTacToeGame ticTacToeGame new TicTacToeGame();ticTacToeGame.start();}}//TicTacToeGame 方法類import java.util.Scanner;public class TicTacToeGa…

Session(數據)共享的前后端分離Shiro實戰

1&#xff0c;前言本文期望描述如何使用Shiro構建基本的安全登錄和權限驗證。本文實戰場景有如下特殊需求&#xff1a;1&#xff0c;在集群和分布式環境實現session共享&#xff1b;2&#xff0c;前端只使用HTML/CSS/JS。因此無法直接使用Shiro提供的SessionManager&#xff0c…

讀書筆記(javascript 高級程序設計)

一. 數據類型&#xff1a; 1. undefined&#xff1a; 未聲明和未初始化的變量&#xff0c;typeof 操作符返回的結果都是 undefined&#xff1b;&#xff08;建議未初始化的變量進行顯式賦值&#xff0c;這樣當 typeof 返回 undefined 時就知道是未聲明了&#xff0c;幫助定位問…

關于gcc擴展中的宏定義中用 # 和 ##

關于gcc擴展中的宏定義中用 "#" 和 "##"今天測試了宏定義中的 "#" 和 "##" 的區別。 結果如下&#xff1a; "#" 代表和一個字符串相連接 "##" 代表和一個符號連接&#xff0c;符號可以是變量&#xff0c;或另一…

java 年計算_java實現計算某年某月的天數

在計算某年某月的天數時&#xff0c;需要注意平年閏年。分析&#xff1a;閏年具體的判定方法就要看它的判定條件&#xff1a;四年一閏 &#xff0c; 百年不閏 &#xff0c;400年再閏。而計算該年該月的天數&#xff0c;又分大月和小月&#xff0c;特殊月份2月之分。(視頻教程推…

添加自定義菜單,報錯40155

2019獨角獸企業重金招聘Python工程師標準>>> 提交的json中&#xff0c;某個自定義菜單對應的URL訪問是有問題的&#xff0c;請挨個檢查一下。 轉載于:https://my.oschina.net/selly1025/blog/1551496

gcc編譯流程及中間表示層RTL的探索

gcc編譯流程及中間表示層RTL的探索收藏新一篇: 解讀VC編程中的文件操作API和CFile類 | 舊一篇: Effective Item21 盡可能使用const 內容摘要 本文將以 C 語言為例&#xff0c;介紹 gcc 在接受一個 .c文件的輸入之后&#xff0c;其前端是如何進行處理并得到一個中間表示并轉交給…

【bzoj2132】圈地計劃 網絡流最小割

題目描述 最近房地產商GDOI(Group of Dumbbells Or Idiots)從NOI(Nuts Old Idiots)手中得到了一塊開發土地。據了解&#xff0c;這塊土地是一塊矩形的區域&#xff0c;可以縱橫劃分為NM塊小區域。GDOI要求將這些區域分為商業區和工業區來開發。根據不同的地形環境&#xff0c;每…

python爬蟲爬取數據如何將br去掉_Python怎么去除爬取下來的網站中的一些轉義字符串 - 收獲啦...

基本方法其實用python爬取網頁很簡單&#xff0c;只有簡單的幾句話這樣就可以獲得到頁面的內容。接下來再用正則匹配去匹配所需要的內容就行了。但是&#xff0c;真正要做起來&#xff0c;就會有各種各樣的細節問題。2.登錄這是一個需要登錄認證的網站。也不太難&#xff0c;只…

Linux基礎

Linux的特點&#xff1a; 系統版本&#xff1a;常見的有debian、Redhat更適合做服務器&#xff0c;更安全和穩定&#xff0c;Ubuntu唯一的優勢就是圖形界面好&#xff0c;centos目前被redhat收購&#xff0c;紅旗已經倒閉。 1、免費的/開源的&#xff1b;2、支持多線程/多用戶&…

GCC的編譯和調試--入門介紹

編譯與調試1.1編譯的概念和理解在進行C程序開發時&#xff0c;編譯就是將編寫的C語言代碼變成可執行程序的過程&#xff0c;這一過程是由編譯器來完成的。編譯器就是完成程序編譯工作的軟件&#xff0c;在進行程序編譯時完成了一系列復雜的過程。1.1.1程序編譯的過程在執行這一…

A* a=new B ,會不會產生內存泄露了,露了B-A的部分?

A* anew B ,delete a;會不會產生內存泄露了&#xff0c;露了B-A的部分。其中B為A的子類 析構函數在下邊3種情況時被調用&#xff1a;1.對象生命周期結束&#xff0c;被銷毀時&#xff1b;2.delete指向對象的指針時&#xff0c;或delete指向對象的基類類型指針&#xff0c;而其基…

spring 第一天:1015

對象加強的三種方法&#xff1a;1/繼承2/裝飾著模式3/動態調用 2&#xff1a;裝飾著模式&#xff1a;就是就是1-先建一個基類 &#xff0c;如咖啡類 。味道很苦2- 再建一個類配料類 也就是說是所欲配料種類的父類。然后寫多配料子類個子類繼承配料類&#xff0c;。3-子類三個步…

java public 繼承_java繼承問題

代碼&#xff1a;父類&#xff1a;public class Father {public Father() {System.out.println("基類構造函數{");show();new a();System.out.println("}");}public void show() {System.out.println("基類----show");}public class a {public a…

BZOJ 1662: [Usaco2006 Nov]Round Numbers 圓環數(數位DP+惡心細節)

BZOJ 1662: [Usaco2006 Nov]Round Numbers 圓環數 Time Limit: 5 Sec Memory Limit: 64 MBDescription 正如你所知&#xff0c;奶牛們沒有手指以至于不能玩“石頭剪刀布”來任意地決定例如誰先擠奶的順序。她們甚至也不能通過仍硬幣的方式。 所以她們通過"round number&q…

Optimizing Code with GCC

現在的編譯器越來越聰明&#xff0c;功能越來越強&#xff0c;從簡單的函數內聯&#xff0c;到復雜的寄存器分析&#xff0c;一系列代碼革命使程序運行得越來越快。大多數時候&#xff0c;更快比更小重要&#xff0c;因為磁盤空間和內存都變得便宜了。但是在嵌入式系統里&#…

QTP的那些事--操作excel的函數

1: QTP Excel函數 操作EXCEL 數據表格 表單 編輯EXCEL 工作表 2: Dim ExcelApp As Excel.Application 3: Dim excelSheet As Excel.worksheet 4: Dim excelBook As Excel.workbook 5: Dim fso As scrīpting.FileSystemObject 6: 7: ******************…