GCC精彩之旅

在為Linux開發應用程序時,絕大多數情況下使用的都是C語言,因此幾乎每一位Linux程序員面臨的首要問題都是如何靈活運用C編譯器。目前 Linux下最常用的C語言編譯器是GCC(GNU Compiler Collection),它是GNU項目中符合ANSI C標準的編譯系統,能夠編譯用C、C++和Object C等語言編寫的程序。GCC不僅功能非常強大,結構也異常靈活。最值得稱道的一點就是它可以通過不同的前端模塊來支持各種語言,如Java、 Fortran、Pascal、Modula-3和Ada等。

開放、自由和靈活是Linux的魅力所在,而這一點在GCC上的體現就是程序員通過它能夠更好地控制整個編譯過程。在使用GCC編譯程序時,編譯過程可以被細分為四個階段:

◆ 預處理(Pre-Processing)

◆ 編譯(Compiling)

◆ 匯編(Assembling)

◆ 鏈接(Linking)

Linux 程序員可以根據自己的需要讓GCC在編譯的任何階段結束,以便檢查或使用編譯器在該階段的輸出信息,或者對最后生成的二進制文件進行控制,以便通過加入不 同數量和種類的調試代碼來為今后的調試做好準備。和其它常用的編譯器一樣,GCC也提供了靈活而強大的代碼優化功能,利用它可以生成執行效率更高的代碼。

GCC提供了30多條警告信息和三個警告級別,使用它們有助于增強程序的穩定性和可移植性。此外,GCC還對標準的C和C++語言進行了大量的擴展,提高程序的執行效率,有助于編譯器進行代碼優化,能夠減輕編程的工作量。

GCC起步

在學習使用GCC之前,下面的這個例子能夠幫助用戶迅速理解GCC的工作原理,并將其立即運用到實際的項目開發中去。首先用熟悉的編輯器輸入清單1所示的代碼:

清單1:hello.c

#include <stdio.h>
int main(void)
{
printf ("Hello world, Linux programming!n");
return 0;
}

然后執行下面的命令編譯和運行這段程序:

# gcc hello.c -o hello
# ./hello
Hello world, Linux programming!

從 程序員的角度看,只需簡單地執行一條GCC命令就可以了,但從編譯器的角度來看,卻需要完成一系列非常繁雜的工作。首先,GCC需要調用預處理程序 cpp,由它負責展開在源文件中定義的宏,并向其中插入“#include”語句所包含的內容;接著,GCC會調用ccl和as將處理后的源代碼編譯成目 標代碼;最后,GCC會調用鏈接程序ld,把生成的目標代碼鏈接成一個可執行程序。

為了更好地理解GCC的工作過程,可以把上述編譯過程分成幾個步驟單獨進行,并觀察每步的運行結果。第一步是進行預編譯,使用-E參數可以讓GCC在預處理結束后停止編譯過程:

#??gcc -E hello.c -o hello.i

此時若查看hello.cpp文件中的內容,會發現stdio.h的內容確實都插到文件里去了,而其它應當被預處理的宏定義也都做了相應的處理。下一步是將hello.i編譯為目標代碼,這可以通過使用-c參數來完成:

#??gcc -c hello.i -o hello.o

GCC默認將.i文件看成是預處理后的C語言源代碼,因此上述命令將自動跳過預處理步驟而開始執行編譯過程,也可以使用-x參數讓GCC從指定的步驟開始編譯。最后一步是將生成的目標文件鏈接成可執行文件:

#??gcc hello.o -o hello

在 采用模塊化的設計思想進行軟件開發時,通常整個程序是由多個源文件組成的,相應地也就形成了多個編譯單元,使用GCC能夠很好地管理這些編譯單元。假設有 一個由foo1.c和foo2.c兩個源文件組成的程序,為了對它們進行編譯,并最終生成可執行程序foo,可以使用下面這條命令:

#??gcc foo1.c foo2.c -o foo

如果同時處理的文件不止一個,GCC仍然會按照預處理、編譯和鏈接的過程依次進行。如果深究起來,上面這條命令大致相當于依次執行如下三條命令:

# gcc -c foo1.c -o foo1.o
# gcc -c foo2.c -o foo2.o
# gcc foo1.o foo2.o -o foo

在 編譯一個包含許多源文件的工程時,若只用一條GCC命令來完成編譯是非常浪費時間的。假設項目中有100個源文件需要編譯,并且每個源文件中都包含 10000行代碼,如果像上面那樣僅用一條GCC命令來完成編譯工作,那么GCC需要將每個源文件都重新編譯一遍,然后再全部連接起來。很顯然,這樣浪費 的時間相當多,尤其是當用戶只是修改了其中某一個文件的時候,完全沒有必要將每個文件都重新編譯一遍,因為很多已經生成的目標文件是不會改變的。要解決這 個問題,關鍵是要靈活運用GCC,同時還要借助像Make這樣的工具。

警告提示功能

GCC包含完整的出錯檢查和警告提示功能,它們可以幫助Linux程序員寫出更加專業和優美的代碼。先來讀讀清單2所示的程序,這段代碼寫得很糟糕,仔細檢查一下不難挑出很多毛病:

◆main函數的返回值被聲明為void,但實際上應該是int;

◆使用了GNU語法擴展,即使用long long來聲明64位整數,不符合ANSI/ISO C語言標準;

◆main函數在終止前沒有調用return語句。

清單2:illcode.c

#include <stdio.h>
void main(void)
{
??long long int var = 1;
??printf("It is not standard C code!n");
}

下面來看看GCC是如何幫助程序員來發現這些錯誤的。當GCC在編譯不符合ANSI/ISO C語言標準的源代碼時,如果加上了-pedantic選項,那么使用了擴展語法的地方將產生相應的警告信息:

# gcc -pedantic illcode.c -o illcode
illcode.c: In function `main':
illcode.c:9: ISO C89 does not support `long long'
illcode.c:8: return type of `main' is not `int'

需 要注意的是,-pedantic編譯選項并不能保證被編譯程序與ANSI/ISO C標準的完全兼容,它僅僅只能用來幫助Linux程序員離這個目標越來越近。或者換句話說,-pedantic選項能夠幫助程序員發現一些不符合 ANSI/ISO C標準的代碼,但不是全部,事實上只有ANSI/ISO C語言標準中要求進行編譯器診斷的那些情況,才有可能被GCC發現并提出警告。

除了-pedantic之外,GCC還有一些其它編譯選項也能夠產生有用的警告信息。這些選項大多以-W開頭,其中最有價值的當數-Wall了,使用它能夠使GCC產生盡可能多的警告信息:

# gcc -Wall illcode.c -o illcode
illcode.c:8: warning: return type of `main' is not `int'
illcode.c: In function `main':
illcode.c:9: warning: unused variable `var'

GCC給出的警告信息雖然從嚴格意義上說不能算作是錯誤,但卻很可能成為錯誤的棲身之所。一個優秀的Linux程序員應該盡量避免產生警告信息,使自己的代碼始終保持簡潔、優美和健壯的特性。

在 處理警告方面,另一個常用的編譯選項是-Werror,它要求GCC將所有的警告當成錯誤進行處理,這在使用自動編譯工具(如Make等)時非常有用。如 果編譯時帶上-Werror選項,那么GCC會在所有產生警告的地方停止編譯,迫使程序員對自己的代碼進行修改。只有當相應的警告信息消除時,才可能將編 譯過程繼續朝前推進。執行情況如下:

# gcc -Wall -Werror illcode.c -o illcode
cc1: warnings being treated as errors
illcode.c:8: warning: return type of `main' is not `int'
illcode.c: In function `main':
illcode.c:9: warning: unused variable `var'

對Linux程序員來講,GCC給出的警告信息是很有價值的,它們不僅可以幫助程序員寫出更加健壯的程序,而且還是跟蹤和調試程序的有力工具。建議在用GCC編譯源代碼時始終帶上-Wall選項,并把它逐漸培養成為一種習慣,這對找出常見的隱式編程錯誤很有幫助。

在Linux 下開發軟件時,完全不使用第三方函數庫的情況是比較少見的,通常來講都需要借助一個或多個函數庫的支持才能夠完成相應的功能。從程序員的角度看,函數庫實 際上就是一些頭文件(.h)和庫文件(.so或者.a)的集合。雖然Linux下的大多數函數都默認將頭文件放到/usr/include/目錄下,而庫 文件則放到/usr/lib/目錄下,但并不是所有的情況都是這樣。正因如此,GCC在編譯時必須有自己的辦法來查找所需要的頭文件和庫文件。

GCC采用搜索目錄的辦法來查找所需要的文件,-I選項可以向GCC的頭文件搜索路徑中添加新的目錄。例如,如果在/home/xiaowp/include/目錄下有編譯時所需要的頭文件,為了讓GCC能夠順利地找到它們,就可以使用-I選項:

# gcc foo.c -I /home/xiaowp/include -o foo

同樣,如果使用了不在標準位置的庫文件,那么可以通過-L選項向GCC的庫文件搜索路徑中添加新的目錄。例如,如果在/home/xiaowp/lib/目錄下有鏈接時所需要的庫文件libfoo.so,為了讓GCC能夠順利地找到它,可以使用下面的命令:

# gcc foo.c -L /home/xiaowp/lib -lfoo -o foo

值 得好好解釋一下的是-l選項,它指示GCC去連接庫文件libfoo.so。Linux下的庫文件在命名時有一個約定,那就是應該以lib三個字母開頭, 由于所有的庫文件都遵循了同樣的規范,因此在用-l選項指定鏈接的庫文件名時可以省去lib三個字母,也就是說GCC在對-lfoo進行處理時,會自動去 鏈接名為libfoo.so的文件。

Linux下的庫文件分為兩大類分別是動態鏈接庫(通常以.so結尾)和靜態鏈接庫(通常以.a 結尾),兩者的差別僅在程序執行時所需的代碼是在運行時動態加載的,還是在編譯時靜態加載的。默認情況下,GCC在鏈接時優先使用動態鏈接庫,只有當動態 鏈接庫不存在時才考慮使用靜態鏈接庫,如果需要的話可以在編譯時加上-static選項,強制使用靜態鏈接庫。例如,如果在 /home/xiaowp/lib/目錄下有鏈接時所需要的庫文件libfoo.so和libfoo.a,為了讓GCC在鏈接時只用到靜態鏈接庫,可以使 用下面的命令:

# gcc foo.c -L /home/xiaowp/lib -static -lfoo -o foo
代碼優化

代 碼優化指的是編譯器通過分析源代碼,找出其中尚未達到最優的部分,然后對其重新進行組合,目的是改善程序的執行性能。GCC提供的代碼優化功能非常強大, 它通過編譯選項-On來控制優化代碼的生成,其中n是一個代表優化級別的整數。對于不同版本的GCC來講,n的取值范圍及其對應的優化效果可能并不完全相 同,比較典型的范圍是從0變化到2或3。

編譯時使用選項-O可以告訴GCC同時減小代碼的長度和執行時間,其效果等價于-O1。在這 一級別上能夠進行的優化類型雖然取決于目標處理器,但一般都會包括線程跳轉(Thread Jump)和延遲退棧(Deferred Stack Pops)兩種優化。選項-O2告訴GCC除了完成所有-O1級別的優化之外,同時還要進行一些額外的調整工作,如處理器指令調度等。選項-O3則除了完 成所有-O2級別的優化之外,還包括循環展開和其它一些與處理器特性相關的優化工作。通常來說,數字越大優化的等級越高,同時也就意味著程序的運行速度越 快。許多Linux程序員都喜歡使用-O2選項,因為它在優化長度、編譯時間和代碼大小之間,取得了一個比較理想的平衡點。

下面通過具體實例來感受一下GCC的代碼優化功能,所用程序如清單3所示。

清單3:optimize.c

#include <stdio.h>

int main(void)

{?

?double counter;??

double result;??

double temp;??

for (counter = 0;? ? counter < 2000.0 * 2000.0 * 2000.0??/ 20.0 + 2020;? ? counter += (5 - 1) / 4)

{? ? temp = counter / 1979;? ? result??= counter;? ?? ?}?

?printf("Result is %lfn", result);?

?return 0;

}

首先不加任何優化選項進行編譯:

# gcc -Wall optimize.c -o optimize

借助Linux提供的time命令,可以大致統計出該程序在運行時所需要的時間:

# time ./optimizeResult is 400002019.000000real? ? 0m14.942suser? ? 0m14.940ssys? ???0m0.000s

接下去使用優化選項來對代碼進行優化處理:

# gcc -Wall -O optimize.c -o optimize

在同樣的條件下再次測試一下運行時間:

# time ./optimizeResult is 400002019.000000real? ? 0m3.256suser? ? 0m3.240ssys? ???0m0.000s

對 比兩次執行的輸出結果不難看出,程序的性能的確得到了很大幅度的改善,由原來的14秒縮短到了3秒。這個例子是專門針對GCC的優化功能而設計的,因此優 化前后程序的執行速度發生了很大的改變。盡管GCC的代碼優化功能非常強大,但作為一名優秀的Linux程序員,首先還是要力求能夠手工編寫出高質量的代 碼。如果編寫的代碼簡短,并且邏輯性強,編譯器就不會做更多的工作,甚至根本用不著優化。

?優化雖然能夠給程序帶來更好的執行性能,但在如下一些場合中應該避免優化代碼:

◆ 程序開發的時候 優化等級越高,消耗在編譯上的時間就越長,因此在開發的時候最好不要使用優化選項,只有到軟件發行或開發結束的時候,才考慮對最終生成的代碼進行優化。

◆ 資源受限的時候 一些優化選項會增加可執行代碼的體積,如果程序在運行時能夠申請到的內存資源非常緊張(如一些實時嵌入式設備),那就不要對代碼進行優化,因為由這帶來的負面影響可能會產生非常嚴重的后果。

◆ 跟蹤調試的時候 在對代碼進行優化的時候,某些代碼可能會被刪除或改寫,或者為了取得更佳的性能而進行重組,從而使跟蹤和調試變得異常困難。

調試

一個功能強大的調試器不僅為程序員提供了跟蹤程序執行的手段,而且還可以幫助程序員找到解決問題的方法。對于Linux程序員來講,GDB(GNU Debugger)通過與GCC的配合使用,為基于Linux的軟件開發提供了一個完善的調試環境。

默 認情況下,GCC在編譯時不會將調試符號插入到生成的二進制代碼中,因為這樣會增加可執行文件的大小。如果需要在編譯時生成調試符號信息,可以使用GCC 的-g或者-ggdb選項。GCC在產生調試符號時,同樣采用了分級的思路,開發人員可以通過在-g選項后附加數字1、2或3來指定在代碼中加入調試信息 的多少。默認的級別是2(-g2),此時產生的調試信息包括擴展的符號表、行號、局部或外部變量信息。級別3(-g3)包含級別2中的所有調試信息,以及 源代碼中定義的宏。級別1(-g1)不包含局部變量和與行號有關的調試信息,因此只能夠用于回溯跟蹤和堆棧轉儲之用。回溯跟蹤指的是監視程序在運行過程中 的函數調用歷史,堆棧轉儲則是一種以原始的十六進制格式保存程序執行環境的方法,兩者都是經常用到的調試手段。

GCC產生的調試符號 具有普遍的適應性,可以被許多調試器加以利用,但如果使用的是GDB,那么還可以通過-ggdb選項在生成的二進制代碼中包含GDB專用的調試信息。這種 做法的優點是可以方便GDB的調試工作,但缺點是可能導致其它調試器(如DBX)無法進行正常的調試。選項-ggdb能夠接受的調試級別和-g是完全一樣 的,它們對輸出的調試符號有著相同的影響。

需要注意的是,使用任何一個調試選項都會使最終生成的二進制文件的大小急劇增加,同時增加程序在執行時的開銷,因此調試選項通常僅在軟件的開發和調試階段使用。調試選項對生成代碼大小的影響從下面的對比過程中可以看出來:

# gcc optimize.c -o optimize

# ls optimize -l-rwxrwxr-x??1 xiaowp? ?xiaowp??11649 Nov 20 08:53 optimize??(未加調試選項)

# gcc -g optimize.c -o optimize

# ls optimize -l-rwxrwxr-x??1 xiaowp? ?xiaowp??15889 Nov 20 08:54 optimize??(加入調試選項)

雖然調試選項會增加文件的大小,但事實上Linux中的許多軟件在測試版本甚至最終發行版本中仍然使用了調試選項來進行編譯,這樣做的目的是鼓勵用戶在發現問題時自己動手解決,是Linux的一個顯著特色。

下面還是通過一個具體的實例說明如何利用調試符號來分析錯誤,所用程序見清單4所示。

清單4:crash.c

#include <stdio.h>

?int main(void)

{??

int input =0;??

printf("Input an integer:");??

scanf("%d", input);??

printf("The integer you input is %dn", input);?

?return 0;

}

編譯并運行上述代碼,會產生一個嚴重的段錯誤(Segmentation fault)如下:

# gcc -g crash.c -o crash

# ./crashInput

an integer:10Segmentation fault

為了更快速地發現錯誤所在,可以使用GDB進行跟蹤調試,方法如下:

# gdb crashGNU gdb Red Hat Linux (5.3post-0.20021129.18rh)……(gdb)

當GDB提示符出現的時候,表明GDB已經做好準備進行調試了,現在可以通過run命令讓程序開始在GDB的監控下運行:

(gdb) runStarting program: /home/xiaowp/thesis/gcc/code/crashInput an integer:10Program received signal SIGSEGV, Segmentation fault.0x4008576b in _IO_vfscanf_internal () from /lib/libc.so.6

仔 細分析一下GDB給出的輸出結果不難看出,程序是由于段錯誤而導致異常中止的,說明內存操作出了問題,具體發生問題的地方是在調用 _IO_vfscanf_internal ( )的時候。為了得到更加有價值的信息,可以使用GDB提供的回溯跟蹤命令backtrace,執行結果如下:

(gdb) backtrace

#0??0x4008576b in _IO_vfscanf_internal () from /lib/libc.so.6

#1??0xbffff0c0 in ?? ()

#2??0x4008e0ba in scanf () from /lib/libc.so.6

#3??0x08048393 in main () at crash.c:11

#4??0x40042917 in __libc_start_main () from /lib/libc.so.6

跳過輸出結果中的前面三行,從輸出結果的第四行中不難看出,GDB已經將錯誤定位到crash.c中的第11行了。現在仔細檢查一下:

(gdb) frame 3

#3??0x08048393 in main () at crash.c:1111? ?? ? scanf("%d", input);

使用GDB提供的frame命令可以定位到發生錯誤的代碼段,該命令后面跟著的數值可以在backtrace命令輸出結果中的行首找到。現在已經發現錯誤所在了,應該將

scanf("%d", input);改為scanf("%d", &input);

完成后就可以退出GDB了,命令如下:

(gdb) quit

GDB的功能遠遠不止如此,它還可以單步跟蹤程序、檢查內存變量和設置斷點等。

調 試時可能會需要用到編譯器產生的中間結果,這時可以使用-save-temps選項,讓GCC將預處理代碼、匯編代碼和目標代碼都作為文件保存起來。如果 想檢查生成的代碼是否能夠通過手工調整的辦法來提高執行性能,在編譯過程中生成的中間文件將會很有幫助,具體情況如下:

# gcc -save-temps foo.c -o foo

# ls foo*foo??foo.c??foo.i??foo.s

GCC 支持的其它調試選項還包括-p和-pg,它們會將剖析(Profiling)信息加入到最終生成的二進制代碼中。剖析信息對于找出程序的性能瓶頸很有幫 助,是協助Linux程序員開發出高性能程序的有力工具。在編譯時加入-p選項會在生成的代碼中加入通用剖析工具(Prof)能夠識別的統計信息,而- pg選項則生成只有GNU剖析工具(Gprof)才能識別的統計信息。

最后提醒一點,雖然GCC允許在優化的同時加入調試符號信息, 但優化后的代碼對于調試本身而言將是一個很大的挑戰。代碼在經過優化之后,在源程序中聲明和使用的變量很可能不再使用,控制流也可能會突然跳轉到意外的地 方,循環語句有可能因為循環展開而變得到處都有,所有這些對調試來講都將是一場噩夢。建議在調試的時候最好不使用任何優化選項,只有當程序在最終發行的時 候才考慮對其進行優化。
上次的培訓園地中介紹了GCC的編譯過程、警告提示功能、庫依賴、代碼優化和程序調試六個方面的內容。這期是最后的一部分內容。
在將源代碼變成可執行文件的過程中,需要經過許多中間步驟,包含預處理、編譯、匯編和連接。這些過程實際上是由不同的程序負責完成的。大多數情況下GCC可以為Linux程序員完成所有的后臺工作,自動調用相應程序進行處理。

這 樣做有一個很明顯的缺點,就是GCC在處理每一個源文件時,最終都需要生成好幾個臨時文件才能完成相應的工作,從而無形中導致處理速度變慢。例如,GCC 在處理一個源文件時,可能需要一個臨時文件來保存預處理的輸出、一個臨時文件來保存編譯器的輸出、一個臨時文件來保存匯編器的輸出,而讀寫這些臨時文件顯 然需要耗費一定的時間。當軟件項目變得非常龐大的時候,花費在這上面的代價可能會變得很沉重。

解決的辦法是,使用Linux提供的一種更加高效的通信方式—管道。它可以用來同時連接兩個程序,其中一個程序的輸出將被直接作為另一個程序的輸入,這樣就可以避免使用臨時文件,但編譯時卻需要消耗更多的內存。

在編譯過程中使用管道是由GCC的-pipe選項決定的。下面的這條命令就是借助GCC的管道功能來提高編譯速度的:

# gcc -pipe foo.c -o foo

在編譯小型工程時使用管道,編譯時間上的差異可能還不是很明顯,但在源代碼非常多的大型工程中,差異將變得非常明顯。

文件擴展名

在使用GCC的過程中,用戶對一些常用的擴展名一定要熟悉,并知道其含義。為了方便大家學習使用GCC,在此將這些擴展名羅列如下:

.c C原始程序;

.C C++原始程序;

.cc C++原始程序;

.cxx C++原始程序;

.m Objective-C原始程序;

.i 已經過預處理的C原始程序;

.ii 已經過預處理之C++原始程序;

.s 組合語言原始程序;

.S 組合語言原始程序;

.h 預處理文件(標頭文件);

.o 目標文件;

.a 存檔文件。

GCC常用選項

GCC作為Linux下C/C++重要的編譯環境,功能強大,編譯選項繁多。為了方便大家日后編譯方便,在此將常用的選項及說明羅列出來如下:

-c 通知GCC取消鏈接步驟,即編譯源碼并在最后生成目標文件;

-Dmacro 定義指定的宏,使它能夠通過源碼中的#ifdef進行檢驗;

-E 不經過編譯預處理程序的輸出而輸送至標準輸出;

-g3 獲得有關調試程序的詳細信息,它不能與-o選項聯合使用;

-Idirectory 在包含文件搜索路徑的起點處添加指定目錄;

-llibrary 提示鏈接程序在創建最終可執行文件時包含指定的庫;

-O、-O2、-O3 將優化狀態打開,該選項不能與-g選項聯合使用;

-S 要求編譯程序生成來自源代碼的匯編程序輸出;

-v 啟動所有警報;

-Wall 在發生警報時取消編譯操作,即將警報看作是錯誤;

-Werror 在發生警報時取消編譯操作,即把報警當作是錯誤;

-w 禁止所有的報警。

小結

GCC 是在Linux下開發程序時必須掌握的工具之一。本文對GCC做了一個簡要的介紹,主要講述了如何使用GCC編譯程序、產生警告信息、調試程序和加快 GCC的編譯速度。對所有希望早日跨入Linux開發者行列的人來說,GCC就是成為一名優秀的Linux程序員的起跑線。

轉載于:https://www.cnblogs.com/dyllove98/archive/2005/10/02/2462122.html

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

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

相關文章

寫出C語言中5種數據類型的名稱及其關鍵字,求C語言中的32個關鍵字及其意思?...

關鍵字如下&#xff1a;一、數據類型關鍵字(12個)&#xff1a;(1) char &#xff1a;聲明字符型變量或函數(2) double &#xff1a;聲明雙精度變量或函數(3) enum &#xff1a;聲明枚舉類型(4) float&#xff1a;聲明浮點型變量或函數(5) int&#xff1a; 聲明整型變量或函數(6…

想要設計自己的微服務?看這篇文章就對了

歡迎大家前往騰訊云社區&#xff0c;獲取更多騰訊海量技術實踐干貨哦~ 本文由我就靜靜地看 發表于云社區專欄 本文通過使用Spring Boot&#xff0c;Spring Cloud和Docker構建的概念驗證應用程序的示例&#xff0c;為了解常見的微服務架構模式提供了一個起點。 該代碼在Github上…

函數的嵌套調用

在函數的內部調用其他的函數 def index(): func() print("index") def func(): index() # def index():# func()# print("index")## def func():# print("func")# index()#def my_max(x,y): #這個函數的作用就是比大小誰大打印出…

mysql 開發進階篇系列 41 mysql日志之慢查詢日志

一.概述 慢查詢日志記錄了所有的超過sql語句( 超時參數long_query_time單位 秒&#xff09;&#xff0c;獲得表鎖定的時間不算作執行時間。慢日志默認寫入到參數datadir(數據目錄)指定的路徑下。默認文件名是[hostname]_slow.log&#xff0c;默認超時是10秒&#xff0c;默認不開…

分數相同名次排名規則C語言,如何給數據排名(相同分數相同名次)-excel篇

使用Rank函數來做數據排名該函數是返回一個數值在一個數字列表中的排名。語法&#xff1a;RANK(number,ref,order)RANK(對象,范圍,參數)number(必填參數):是特定單位格中的數據&#xff0c;需要在整個數字列表中排名的單個對象。ref(必填參數):是指需要排名的整體數列。即范圍&…

子窗體列表在菜單中的實現

想在菜單中加入子窗體的列表&#xff0c;上網找了半天&#xff0c;都很麻煩&#xff0c;后來看看了菜單的屬性&#xff0c;發現里面有個MdiList屬性&#xff0c;設置成true&#xff0c;搞定&#xff0c;暈。 轉載于:https://www.cnblogs.com/catzhou/articles/258450.html

MySql的連接查詢

若一個查詢同時涉及到兩個或者兩個以上的表&#xff0c;則稱之為連接查詢。常見的包括&#xff1a;等值連接查詢&#xff0c;自然連接查詢&#xff0c;非等值連接查詢&#xff0c;自身連接查詢&#xff0c;外連接查詢&#xff08;左右連接&#xff09;。 1.等值與非等值連接查詢…

linux下ssh通過公鑰登錄服務器

經常會通過ssh登錄遠程服務器&#xff0c;一種是通過密碼方式登錄&#xff0c;一種是通過公鑰登錄。 如何設置通過公鑰登錄服務器 1. 首先生成自己的公鑰和私鑰 ssh-keygen 命令用來生成公鑰和私鑰-t 用來指定密鑰類型&#xff08;dsa | ecdsa | ed25519 | rsa | rsa1&#xff…

qt運行C語言后無顯示,qt designer啟動后不顯示界面問題的原因與解決辦法-站長資訊中心...

Qt 5.6.1無論是在vs里雙擊ui文件還是直接啟動designer.exe都一直無法顯示界面&#xff0c;但任務管理器中可以看到該進程是存在的。前幾天還正常的&#xff0c;但昨天加了一塊NVIDIA的顯卡(機器自帶核顯)&#xff0c;可能與此有關。幸好還可以通過QtCreator打開ui文件進行編輯。…

OpenSolaris北京用戶組的第一次活動

OpenSolaris北京用戶組的第一次活動作者: BadcoffeeEmail: blog.olivergmail.comBlog: http://blog.csdn.net/yayong2005年10月10月15號&#xff0c;OpenSolaris北京用戶組在北京西郊賓館會議廳組織了成立以來的第一次活動。盡管OpenSolaris早在2005年6月14日就正式開放源代碼&…

. SQL多條件查詢存儲過程

編輯器加SQL多條件查詢存儲過程 2010-05-13 17:06:29| 分類&#xff1a; SQL | 標簽&#xff1a; |字號大中小 訂閱 . 例一、 ALTER proc SelectProduct ProdID varchar(10), ProdName nvarchar(30), CategoryID varchar(5), MinPrice decimal(10,2), MaxPrice decimal(10,2) a…

矩陣轉置c語言的思路,矩陣轉置 (C語言代碼)

解題思路:注意事項:參考代碼:#includeint main(){int n,s[100][100];void transposition(int(*p)[100], int n);scanf("%d", &n);for (int i 0; i < n; i){for (int j 0; j < n; j)scanf("%d", *(s i) j);}transposition(s, n);return 0;}vo…

Android PermissionUtils:運行時權限工具類及申請權限的正確姿勢

Android PermissionUtils&#xff1a;運行時權限工具類及申請權限的正確姿勢 ifadai 關注 2017.06.16 16:22* 字數 318 閱讀 3637評論 1喜歡 6PermissionUtil 經常寫Android運行時權限申請代碼&#xff0c;每次都是復制過來之后&#xff0c;改一下權限字符串就用&#xff0c;把…

實現帶下拉菜單的工具欄按鈕

在工具欄中使用真彩色圖標 實現帶下拉菜單的工具欄按鈕 20050916轉載于:https://www.cnblogs.com/henryzc/archive/2005/11/08/271346.html

文件目錄管理與顯示c語言,Centos 7 文件和目錄管理

查看權限在終端輸入:ls -l xxx.xxx (xxx.xxx是文件名)那么就會出現相類似的信息&#xff0c;主要都是這些&#xff1a;-rw-rw-r--其中&#xff1a; 最前面那個 - 代表的是類型中間那三個 rw- 代表的是所有者(user)然后那三個 rw- 代表的是組群(group)最后那三個 r-- 代表的是…

Linux基礎監控小工具nmon

nmon是一種在AIX與各種Linux操作系統上廣泛使用的監控與分析工具&#xff0c; nmon所記錄的信息是比較全面的&#xff0c;它能在系統運行過程中實時地捕捉系統資源的使用情況&#xff0c;并且能輸出結果到文件中。nmon工具可以幫助在一個屏幕上顯示所有重要的性能優化信息&…

vue的配置環境篇

1.電腦已經安裝的nodejs和webpack。 2.1&#xff09;打開cmd。winr。可以直接輸入node -v查看版本。安裝淘寶鏡像 npm install -g cnpm --registryhttp://registry.npm.taobao.org &#xff0c;安裝成功可以查看下&#xff0c;cnpm -v 3.安裝vue腳手架&#xff0c;輸入命令&am…

最近比較毀硬件

上上周末公司機器主板南橋在一股青煙中壯烈犧牲……前天家里機器的GF4 Ti4600也半死不活了&#xff0c;不能裝驅動&#xff0c;只能用640x480 16色裝了驅動系統就無法啟動&#xff0c;靠靠的從肥巖那弄了塊GF FX5600XT 機器算是能亮了郁悶阿轉載于:https://www.cnblogs.com/sko…

行列式運算算法c語言,新手作品:行列式計算C語言版

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓對話 ControlHeightDecrease ShiftUp Arrow 向上調整選定的控件或對話一個對話單位對話 ControlHeightIncrease ShiftDown Arrow 向下調整選定的控件或對話一個對話單位對話 ControlMoveDown Dow…

CentOSLinux安裝Docker容器

Docker 使用 環境說明 CentOS 7.3&#xff08;不準確地說&#xff1a;要求必須是 CentOS 7 64位&#xff09;不建議在 Windows 上使用Docker 基本概念 官網&#xff1a;https://www.docker.com/宿主機&#xff1a;安裝 Docker 的那臺電腦Docker&#xff1a;一個虛擬化軟件&…