我們目前正在通過一些非常舊的C++/CLI-代碼(舊語法.NET測試版)的挖掘,都感到有點驚訝地看到這樣的事情:爲什麼printf使用受管理的字符串?
System::String ^source("Test-String");
printf("%s", source);
程序正確輸出
Test-String
我們想知道,爲什麼可以將託管字符串源傳遞到printf
- 更重要的是:爲什麼它可以工作?我不希望它是由編譯器一些便利特徵,因爲以下不工作:
System::String ^source("Test-String");
char pDest[256];
strcpy(pDest, source);
這將產生一個(不知何故預期)編譯錯誤,指出System::String^
不能轉換爲const char*
。所以我唯一真正的解釋是,將託管引用傳遞給va_list會超過所有編譯器檢查,並欺騙本地代碼,使用指向託管堆的指針。由於System::String
表示類似於char
-陣列中的內存,printf
可能工作。或者編譯器轉換爲pin_ptr
並將其傳遞給printf
。
我不指望它會自動將String^
編組到char*
,因爲這會導致內存泄漏不良,而不會引用實際的內存地址。
我們知道這不是一個好的解決方案,而後來由Visual Studio-Versions引入的各種編組方法提供了一種更好的方法,但理解這裏實際發生的事情會非常有趣。
謝謝!
所以也許問題是,*爲什麼編譯器會將它轉換爲IL?從什麼時候開始'printf'是一個託管函數?爲什麼是P /調用它?爲什麼它不像其他本地C++函數那樣調用它? – 2012-08-06 23:19:26
@CodyGray我懷疑是因爲編譯器認爲需要首先通過編組器才能看到需要的東西。我會稍微核實並寫一些更全面的內容。 – vcsjones 2012-08-06 23:24:30
感謝迄今爲止的答案!對我來說,strcpy和sprintf之間關於託管字符串的唯一真正區別是sprintf採用變量arg-list而strcpy不能。也許這就是IL代碼的原因。 – Excelcius 2012-08-07 07:40:42