2010-06-11 68 views
7

引用程序名稱時認爲最佳實踐是什麼?我已經看到了:在C中引用程序名稱時的最佳做法

#define PROGRAM_NAME "myprog" 
printf("this is %s\n", PROGRAM_NAME); 

還有:

printf("this is %s\n", argv[0]); 

我知道,那第二種方法會給我./myprog而非myprog當程序不從$PATH和第一種方法叫做將保證程序名稱的一致性。

但是還有什麼其他的東西讓一種方法優於另一種?

+0

如果你想要一個常量,使用一個常量(即在全局級別,const char * const PROGRAM_NAME =「myprog」;')。這樣做將確保字符串只在內存中存儲一​​次。 – mk12 2012-08-17 21:16:02

回答

5

第二種方法是優越的,當你有多個鏈接。在* nix系統中,有時行爲取決於你如何調用一個程序。所以編寫程序名稱的硬編碼顯然是一個問題 - 它無法檢查。

+0

這是什麼意思「行爲取決於你如何調用程序」?我無法真正理解它。 – guest 2010-06-11 17:48:22

+0

@guest:例如'gcc'和'g ++'可能是同一個可執行文件,它會檢查調用的名稱並相應地修改鏈接器選項。不記得它是否真的存在。 – 2010-06-11 17:51:38

+0

例如:默認情況下,grep打印匹配的行。另外,還有三個變體程序egrep,fgrep和rgrep。 egrep與grep -E相同。 fgrep與grep -F相同。 rgrep與grep -r相同。 – 2010-06-11 17:54:00

0

前者優於後者,當你手邊沒有argv時。

#define PROGRAM_NAME "myprog" 

void salute() 
{ 
    // no argv available 

    printf("Hello from %s\n", PROGRAM_NAME); 
} 

void main(int argc, char** argv) 
{ 
    salute(); 
} 
+0

是否會產生如此大的差異?我不認爲'argc'和'argv'成本太高了啊 – guest 2010-06-11 17:38:13

+0

啊。我明白你的意思了。是的,非常有意義 – guest 2010-06-11 17:40:31

+1

我明白了你的觀點,但在你的例子中,你基本上正在創建一個全局變量。如果您需要program_name,然後將它作爲參數傳遞給(),並且您的問題已解決。 – MJB 2010-06-11 17:42:35

0

取決於argv是否在範圍或不...

5

我試圖採取兩全其美的:

char const * program_name; 

int main(int argc, char **argv) { 
    program_name = argv[0]; 
    //... 
} 

如果您需要程序名是在一些其他的文件可用,你可以聲明它是這樣的:

extern char const * program_name; 

我宣佈「字符const *「,因爲我希望它是一個指向const數據的指針。我不確定我是否正確執行了這部分。

+0

不錯。通過回答「兩者」來回答哪一個更好的問題,但不是不好的。 – MJB 2010-06-11 17:49:11

1

第二種方法可以給你也像/usr/bin/myprog字符串,如果你這樣執行它; basename應該給出可執行文件的名稱(可以認爲是程序的名稱)...除非它是符號鏈接的...(在這種情況下,您可以使用可用的鏈接名稱)在程序行爲中做某種選擇)。

第一種方法「修復」的程序名程序員想要的東西,無論用戶如何改名爲可執行文件或符號鏈接(或者甚至硬鏈接)

+0

是的,我使用的產品看起來像有幾個可執行文件,但實際上它只有一個,並且有多個鏈接。這可能看起來很瘋狂,但它是通過多個修訂保持多個工具同步的好方法。 – 2010-06-11 17:55:13

2

我平時如果有可能使用argv[0],或basename(argv[0])。從用戶的POV中,我認爲如果他們重命名或硬鏈接一個可執行文件(或者其他人爲他們做了這些),那麼他們希望來自它的消息出現在他們正在使用的名稱下,而不是以編譯的其他名稱出現,他們可能會或可能不知道。

同樣,如果您將來發現要使用不同的選項以不同的名稱編譯程序以提供不同的版本,是否要在#define周圍包裝#ifndef並確保它是通過編譯器命令行定義的:-DPROGRAM_NAME=myprog_demo,或者你只是想做到這一點,它的工作原理?

例外可能是,如果您的使用說明是從聯機幫助頁或其他文檔中提取的,那麼可能需要將程序名稱硬連接到該程序名稱。但是你可能不會使用#define

儘管如此,實現方案不需要提供argv[0],因此,爲了實現最好的便攜式實踐,也需要處理這種情況。再次,如果你的系統沒有提供它,那麼用戶可能實際上也不會在任何類型的終端上看到消息。

順便說一句:

#define PROGRAM_NAME "myprog" 
puts("this is " PROGRAM_NAME); 
+0

'basename'不可移植。它只需要POSIX(在libgen.h中)。同樣,請記住,它可能會修改您給它的字符串,並且返回的指針可能是與原始指針或靜態分配的字符串的偏移量(所以不要試圖釋放它給您的東西,並且不要不要試圖釋放你之後給予的*)。我會避免它,除非你100%確定你理解所涉及的內存管理,並且你不關心可移植性。 – mk12 2012-08-17 21:09:33

+1

因此,「如果可能」。但是你說得對,'basename(argv [0])'本身就是一個有點可疑的表達式,它假定你不打算再次使用這個參數。 – 2012-08-21 08:58:13

1

這並不完全回答你的編程最佳實踐的問題,但我想你也應該記住什麼是最好的用戶。 我個人比較喜歡使用argv[0]來引用自己的程序,即我正在調用的命令,而不是程序中編碼器硬編碼的一些隨機名稱。有幾個例子,其中一個硬編碼的名字很討厭,或者至少沒有幫助:

  • 我創建了一個鏈接到一個程序
  • 我已經改名爲二進制出於某種原因
  • 我有多個可執行文件在我的不同目錄中使用相同的基本名稱$PATH
  • 程序給了我一些其他調用方法的提示,例如在「使用」消息中

我更喜歡硬編碼程序名稱的唯一情況是當我使用GUI應用程序時。我不想看到「〜/ foo/bar.pl」作爲窗口標題。

相關問題