2011-05-29 45 views
1
errno_t _dupenv_s(
    char **buffer, 
    size_t *sizeInBytes, 
    const char *varname 
); 

我有這方面的幾個問題:爲什麼這個MSVC API是這樣定義的?

  1. 爲什麼(**)是必需的,而不是一個指針(*)指針的指針?
  2. 爲什麼sizeInBytes是必要的,是不是可以通過strlen(buffer)
+5

可能是因爲函數分配了緩衝區。 – 2011-05-29 04:01:09

+0

@Mauricio Scheffer,是不是'*'足以引用該緩衝區? – 2011-05-29 04:11:47

+1

如果函數分配了緩衝區,則不會。看看一些指針教程。 – 2011-05-29 04:15:04

回答

0

不,它是要求字符指針的地址。該方法將分配必要的空間來保存變量的值,並設置指針的值,否則爲NULL。參見以下示例代碼頁面向下:

http://msdn.microsoft.com/en-us/library/ms175774(v=VS.80).aspx

+0

@ Matt,爲什麼'sizeInBytes'是必需的,是不是'strlen(buffer)'可用的? – 2011-05-29 04:19:54

+0

sizeInBytes告訴你被分配的字符指針的大小(字節數),這個模式被使用,因爲在unicode版本的函數中,一個字符不是一個字節,而是因爲UTF-16而是兩個字節。所以是的,在你的情況下,char *上的strlen將返回正確的值,在unicode中它將是wcslen(buffer),或者取決於編譯器標誌,如果使用tchar確定編譯時是否使用unicode或ansi,則可能是tcslen 。 – Matt 2011-05-29 04:24:36

+0

@matt:msvc crt已經有'strdup'的unicode和多字節版本,那麼爲什麼你會使用utf-16的ascii版本呢? (也就是說沒有這樣的模式,如果你使用utf,你最好使用unicode函數),參見:http://msdn.microsoft.com/en-us/library/y471khhc(v=vs.80).aspx – Necrolis 2011-05-29 05:13:52

0

在這種情況下,類型char**是一個指針的指針的char秒的陣列。 (它也可以指向指向單個指針的指針,但這不是如何與_dupenv_s()一起使用的指針)。

_dupenv_s()函數通過要求操作系統保留足夠大的內存來保存它,從而分配一個數組char。操作系統保留一塊內存,併爲_dupenv_s()函數提供這個新分配的char數組的地址。 _dupenv_s()函數將該數組的地址存儲到char*變量中,因爲它是指向數組char s的指針。

現在,函數必須將此char*值傳遞給調用方,以便調用代碼可以使用它。返回值已用於返回錯誤代碼,因此無法使用。但是讓我們假設調用者有一個char*變量準備好接收分配緩衝區的地址。

如果_dupenv_s()函數知道調用者的char*變量所在的位置,則該函數可以繼續並用正確的值填充調用者的char*變量。要做到這一點,呼叫者需要傳遞呼叫者的變量地址char*。也就是說,您需要將指針傳遞給指向數組chars的指針。這意味着必須通過char**

請注意,這也是sizeInBytessize_t*的原因。調用者有一個變量size_t,調用者可以將該變量的地址作爲size_t*傳遞給該函數,以便函數可以用正確的值填充該變量。

儘管strlen(buffer) == sizeInBytesstrlen()函數可能通過計算字符數來確定字符串的長度,直到它看到空終止符爲止。 strlen()完成所需的時間量與字符的數量成線性關係,即它不是恆定的。爲什麼不避免要求調用者這樣做並直接提供大小的麻煩?


如果指針還在迷惑你(和他們有時混亂),this Stack Overflow answer能有所幫助。

+0

現在我對'char **'有點懷疑,但sizeInBytes'仍然存在問題。那些信息有幫助嗎? – 2011-05-29 06:03:58

4

在msvc下的後綴爲_s的任何函數都是安全函數,這意味着它不會對傳遞的數據的完整性做任何假設。由於這個原因,字符串的長度是必需的,因爲你不能假定它的空終止,或者根本不終止(你也許只想要字符串的一半,但那是副作用)。

安全函數都返回錯誤代碼,以便可以檢查它們而不會出現錯誤,並且由於此任何返回都需要通過指針發送。並且看到strdup的非安全版本& dupenv返回char*,您將獲得雙重間接,以便指向您傳遞的變量的指針獲取分配的緩衝區的地址。