2016-11-04 57 views
2

有一個關於這個問題*argv[]爲什麼使用參數時使用了一個指針?

#include <stdio.h> 
#include <ctype.h> 
#include <math.h> 
#include <string.h> 

int main(int argc, char *argv[]) 
{ 
    if (argc != 2) { 
     fprintf(stderr, "Usage: %s <string>\n", argv[0]); 
     return 1; 
    } 

    char *input = argv[1]; 
    for (int i = 0; i < strlen(input); i++) { 
     if (isalpha(input[i]) == 0) 
      return 1; 
    } 

argc對我來說很有意義,因爲它是一個包含與指令傳遞的參數數目一個int變量。然而,爲什麼argv[]需要成爲一個指針而不是其本身的變量?

在哪裏存儲配置了該參數,是否有限制?是否有可能使用參數而不是fgets來輸入參數?

+4

這是一個指向char的指針數組,指向char的指針是表示字符串的std c方式。 –

+1

http://cdecl.ridiculousfish.com/?q=+char+*argv%5B%5D –

+1

當需要存儲和傳遞不可預知(可變)長度的字符串數組時,「鋸齒狀數組」方法起作用很不錯。鋸齒數組通過指針數組實現。這正是你在這種情況下看到的。 – AnT

回答

3

argv是指向的char*陣列的第一個元素。 C實際上並不具備將數組作爲參數傳遞的能力,它將指針傳遞給數組的第一個元素。

至於存儲器,典型地,參數實際上是存儲作爲與存儲NUL的分離與串的單個的連續塊。 argv引用一個指向每個參數開始的數組,但指針不是獨立分配的。如果你調用一個程序:

foo arg1 arg2 arg3 

在內存中的實際佈局常常是這樣的:

"foo\0arg1\0arg2\0arg3\0" 
^0 ^1 ^2 ^3  

其中插入符指定argv條目指向:

argv = {&caret0, &caret1, &caret2, &caret3, NULL}; 

的這種方法的優點是最小的分配器開銷(它可以作爲一個單獨的塊被分配和釋放,而不會在對齊或堆跟蹤數據上浪費字節)。通常累積長度爲argv或參數總數(取決於操作系統/編譯器)的限制;它很大(在我檢查過的最新系統上,字符串的總長度限制在128KB左右),但是如果在大型文件樹上使用廣泛的glob,則可能會觸及它。

主要問題是參數長度限制,以及所有數據一次被解析/加載的情況,其中fgets通過一次處理一條線來重新使用單個(較小)緩衝區,可以使用較少的內存。但是,如果長度限制是不是主要問題,你總是可以使用xargs轉換會有什麼輸入過線stdin成連續參數到您的程序。這有點奇怪,但並非不可能。

+0

這很有道理。謝謝你的幫助。 – Gates

2

但是爲什麼argv []需要成爲一個指針而不是變量本身呢?

出於同樣的原因,您使用指向任何其他函數的指針:避免複製參數或傳遞數組。 argv需要兩者。通過將argv作爲char *argv[]傳入,只需要複製一個指針而不是可能大量的內存。由於argv是一個數組的數組(字符串是真的指針到字節數組)沒有其他的方式來傳遞它(有人也許能想出一個錯綜複雜的結構)。

因爲這每一個程序運行時有發生這是非常重要的。在70年代和80年代,當C和Unix被開發出來並且計算機內存和CPU很少時,這一點更爲重要。

爲參數提供的內存在哪裏,是否有限制?

參數的內存通常由操作系統或外殼分配。在POSIX系統中,您的程序通常使用exec family of functions which passes in argv之一進行調用。該限制是由操作系統強加的。在POSIX中,您可以從ARG_MAX constant in limits.h中找到它。

是否有可能'捕捉'使用參數而不是fgets輸入?

如上所述,參數的總大小(包括程序名稱)有一個限制。在我的Mac上它是262144字節或256K。在Windows 95 it can be as low as 1024 bytes2048 bytes on Win32。在生成Makefiles(基本上是一堆shell命令)時,我遇到了限制as low as 256 bytes in old VMS systemshave had to maintain extensive code to work around these limits。另一方面,

fgets僅受限於文件系統的最大文件大小。如果您從STDIN讀取,則沒有我知道的限制。

+0

我一直在試圖強迫自己理解爲什麼我使用解引用以及他們實際在做什麼。感謝您的意見,這真的很有幫助。 – Gates

+1

@ZachGates太棒了!這是考慮它的一種方法。內存就像一個存儲位置,您可以立即前往任何單位。一個指針就像是一個說明「存儲單元1234」的便箋。你可以立即去那裏並翻找。按價值傳遞就像說「複製存儲單元1234中的所有東西,並將其移動到我的存儲單元」,這花費時間並佔用空間。指針的下側是如果你對存儲單元1234進行任何改變,則它會影響使用存儲單元1234的每個人。當然,這是非常簡單的。 – Schwern

相關問題