Вземете следния пример:
char* fileName = "C:\windows\system32\kernel32.dll";
uint32_t fileSize = 1163264;
printf("The size of %s is %"PRIu32"n", fileName, fileSize);
Всичко е наред, сега, ако искаме прозрачна Unicode поддръжка чрез tchar.h
кодът ще изглежда така:
TCHAR* fileName = _T("C:\windows\system32\kernel32.dll");
uint32_t fileSize = 1163264;
_tprintf(_T("The size of %s is %")_T(PRIu32)_T("n"), fileName, fileSize);
Това работи, ако е unicode не дефинирани. Въпреки това, ако unicode е дефиниран, компилаторът прекъсва със следната грешка:
error C2308: concatenating mismatched strings
Concatenating wide "The size of %s is %l" with narrow "u"
Сега гледам в Microsoft inttypes.h виждам:
...
#define _PFX_32 "l"
...
#define PRIu32 _PFX_32 "u"
Което означава, че _T(PRIu32)
в горния пример решава да:
_T("l" "u")
... която не може да работи, разбира се и обяснява правилната грешка при съставянето.
Така че въпросът ми е как Microsoft си представя, че използваме техните inttypes.h определя с _tprintf?
Отговори:
3 за отговор № 1Според1 към текущия стандарт C, само един отсимволните последователности (прочетени като: низ) трябва да са с представка от кодиращ префикс, а останалите да бъдат третирани така, че да имат един и същ префикс и да са свързани в един единствен низ.
Префиксът за кодиране се определя от макроса _T. Той ще се реши до нищо, ако UNICODE не е дефиниран, в противен случай ще го прибави L
на аргумента.
Решението би било да се използва макроса _T на първия низ, а на останалите няма макрос и те ще използват едно и също кодиране:
_tprintf(_T("The size of %s is %") PRIu32 "n", fileName, fileSize);
Но версията на Visual Studio, която използвате, не е съвместима с C99, така че тази функция липсва. Изглежда, че това е било поправено във Visual Studio 2015.
Същото използване е показано в примера2 в стандарта.
1 (Цитирано от: ISO / IEC 9899: 201x 6.4.5 Струнни литерали 5)
В транслация фаза 6, многобайтовия характерпоследователности, определени от всяка последователност от символите на съседни символи и идентични с префикс символни символи се свързват в a единична многобайтова символна последователност. Ако някой от символите има префикс за кодиране, получената многобайтова символна последователност се третира като имаща същия префикс; в противен случай се третира като буквален символен низ. Дали ли е различен префикс с широк литерал жетоните могат да бъдат свързани и ако е така, третирането на получения мултибайтов характер последователността са дефинирани за изпълнение.
2 (Цитирано от: ISO / IEC 9899: 201x 7.8.1 Макроси за спецификатори на формат 7)
wprintf(L"The largest integer value is %020" PRIxMAX "n", i);