errno_t _dupenv_s(
char **buffer,
size_t *sizeInBytes,
const char *varname
);
我有這方面的幾個問題:爲什麼這個MSVC API是這樣定義的?
- 爲什麼(
**
)是必需的,而不是一個指針(*
)指針的指針? - 爲什麼
sizeInBytes
是必要的,是不是可以通過strlen(buffer)
?
errno_t _dupenv_s(
char **buffer,
size_t *sizeInBytes,
const char *varname
);
我有這方面的幾個問題:爲什麼這個MSVC API是這樣定義的?
**
)是必需的,而不是一個指針(*
)指針的指針?sizeInBytes
是必要的,是不是可以通過strlen(buffer)
?不,它是要求字符指針的地址。該方法將分配必要的空間來保存變量的值,並設置指針的值,否則爲NULL。參見以下示例代碼頁面向下:
http://msdn.microsoft.com/en-us/library/ms175774(v=VS.80).aspx
@ Matt,爲什麼'sizeInBytes'是必需的,是不是'strlen(buffer)'可用的? – 2011-05-29 04:19:54
sizeInBytes告訴你被分配的字符指針的大小(字節數),這個模式被使用,因爲在unicode版本的函數中,一個字符不是一個字節,而是因爲UTF-16而是兩個字節。所以是的,在你的情況下,char *上的strlen將返回正確的值,在unicode中它將是wcslen(buffer),或者取決於編譯器標誌,如果使用tchar確定編譯時是否使用unicode或ansi,則可能是tcslen 。 – Matt 2011-05-29 04:24:36
@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
在這種情況下,類型char**
是一個指針的指針的char
秒的陣列。 (它也可以指向指向單個指針的指針,但這不是如何與_dupenv_s()
一起使用的指針)。
_dupenv_s()
函數通過要求操作系統保留足夠大的內存來保存它,從而分配一個數組char
。操作系統保留一塊內存,併爲_dupenv_s()
函數提供這個新分配的char
數組的地址。 _dupenv_s()
函數將該數組的地址存儲到char*
變量中,因爲它是指向數組char
s的指針。
現在,函數必須將此char*
值傳遞給調用方,以便調用代碼可以使用它。返回值已用於返回錯誤代碼,因此無法使用。但是讓我們假設調用者有一個char*
變量準備好接收分配緩衝區的地址。
如果_dupenv_s()
函數知道調用者的char*
變量所在的位置,則該函數可以繼續並用正確的值填充調用者的char*
變量。要做到這一點,呼叫者需要傳遞呼叫者的變量地址char*
。也就是說,您需要將指針傳遞給指向數組chars
的指針。這意味着必須通過char**
。
請注意,這也是sizeInBytes
是size_t*
的原因。調用者有一個變量size_t
,調用者可以將該變量的地址作爲size_t*
傳遞給該函數,以便函數可以用正確的值填充該變量。
儘管strlen(buffer) == sizeInBytes
,strlen()
函數可能通過計算字符數來確定字符串的長度,直到它看到空終止符爲止。 strlen()
完成所需的時間量與字符的數量成線性關係,即它不是恆定的。爲什麼不避免要求調用者這樣做並直接提供大小的麻煩?
如果指針還在迷惑你(和他們有時混亂),this Stack Overflow answer能有所幫助。
現在我對'char **'有點懷疑,但sizeInBytes'仍然存在問題。那些信息有幫助嗎? – 2011-05-29 06:03:58
在msvc下的後綴爲_s
的任何函數都是安全函數,這意味着它不會對傳遞的數據的完整性做任何假設。由於這個原因,字符串的長度是必需的,因爲你不能假定它的空終止,或者根本不終止(你也許只想要字符串的一半,但那是副作用)。
安全函數都返回錯誤代碼,以便可以檢查它們而不會出現錯誤,並且由於此任何返回都需要通過指針發送。並且看到strdup
的非安全版本& dupenv
返回char*
,您將獲得雙重間接,以便指向您傳遞的變量的指針獲取分配的緩衝區的地址。
可能是因爲函數分配了緩衝區。 – 2011-05-29 04:01:09
@Mauricio Scheffer,是不是'*'足以引用該緩衝區? – 2011-05-29 04:11:47
如果函數分配了緩衝區,則不會。看看一些指針教程。 – 2011-05-29 04:15:04