在 C 语言中,与 printf 和 scanf 函数一起使用的数据类型 BYTE、WORD 和 DWORD 最合适的格式说明符是什么? 我很难通过控制台显示 BPB 字段的值。
例如,如果我尝试使用“%lu”显示 BPB_BytsPerSec,我会得到不寻常的数字..
printf("Bytes per Sector: %lu", b->BPB_BytsPerSec);
我得到的值是“514”,我认为这是错误的解释。请建议出路。谢谢。
(我在 64 位 Windows 上通过 MinGW 使用 gcc 5.1)
这是我们正在讨论的结构:
/* BPB Structure Collected from internet */
struct BPB_FAT32 {
BYTE BS_jmpBoot[3]; // 0
BYTE BS_OEMName[8]; // 3
WORD BPB_BytsPerSec; // 11
BYTE BPB_SecPerClus; // 13
WORD BPB_ResvdSecCnt; // 14
BYTE BPB_NumFATs; // 16
WORD BPB_RootEntCnt; // 17
WORD BPB_TotSec16; // 19
BYTE BPB_Media; // 21
WORD BPB_FATSz16; // 22
WORD BPB_SecPerTrk; // 24
WORD BPB_NumHeads; // 26
DWORD BPB_HiddSec; // 28
DWORD BPB_TotSec32; // 32
DWORD BPB_FATSz32; // 36
WORD BPB_ExtFlags; // 40
WORD BPB_FSVer; // 42
DWORD BPB_RootClus; // 44
WORD BPB_FSInfo; // 48
WORD BPB_BkBootSec; // 50
BYTE BPB_Reserved[12]; // 52
BYTE BS_DrvNum; // 64
BYTE BS_Reserved1; // 65
BYTE BS_BootSig; // 66
DWORD BS_VolID; // 67
BYTE BS_VolLab[11]; // 71
BYTE BS_FilSysType[8]; // 82
};
这是我试图显示这些值的函数..
void DisplayBlock(struct BPB_FAT32* b){
printf("\n\n\t1. Jump to boot code..........: 0x%02x%02x%02x",b->BS_jmpBoot[0],b->BS_jmpBoot[1],b->BS_jmpBoot[2]);
printf("\n\n\t2. OEM name & version.........: "); for(int i=0; i<8;i++) printf("%c",(char)b->BS_OEMName[i]);
printf("\n\n\t3. Bytes per Sector...........: %u",b->BPB_BytsPerSec); // WORD
printf("\n\n\t4. Sectors per Cluster........: %lu", b->BPB_SecPerClus); // BYTE
printf("\n\n\t5. Reserved Sectors Count.....: %lu", b->BPB_ResvdSecCnt); // WORD
printf("\n\n\t6. Number of FAT32 tables.....: %u", b->BPB_NumFATs); // BYTE
printf("\n\n\t7. Number of Root Entries.....: %lu", b->BPB_RootEntCnt); // WORD
printf("\n\n\t8. Total Sectors 16bits.......: %lu",b->BPB_TotSec16); // WORD
printf("\n\n\t9. Media Descriptor...........: %lu",b->BPB_Media); // BYTE 0xF8 is the standard value for fixed media
printf("\n\n\t10. Size According to FAT16....: %lu",b->BPB_FATSz16); // WORD
printf("\n\n\t11. Number of Sector per Track.: %lu",b->BPB_SecPerTrk); // WORD
printf("\n\n\t12. Number of Heads............: %lu",b->BPB_NumHeads); // WORD
printf("\n\n\t13. Number of Hidden Sectors...: %lu", b->BPB_HiddSec); // DWORD
printf("\n\n\t14. Total Sectors 32bits.......: %lu", b->BPB_TotSec32); // DWORD
/* FAT32 Specific Fields Starting offset:36 */
printf("\n\n\t15. Size According to FAT32....: %lu", b->BPB_FATSz32); // DWORD
//printf("\n\n\t16. Extended Flags............: %u",b->BPB_ExtFlags); // WORD Usually 0.
printf("\n\n\t17. File System Version........: %lu", b->BPB_FSVer); // WORD Must be 0:0
printf("\n\n\t18. Root Cluster Number........: %lu",b->BPB_RootClus); // DWORD Usually 2
printf("\n\n\t19. File System Information....: %lu",b->BPB_FSInfo); // WORD
printf("\n\n\t20. Backup Boot Sector.........: %lu",b->BPB_BkBootSec); // WORD Recomended 6
// BYTE BPB_Reserved[12]
/* Remaining common fields FAT12/FAT16 BPB*/
printf("\n\n\t21. Drive Number...............: %u",b->BS_DrvNum); // BYTE
// BYTE BS_Reserved1; /* 65 reserved */
printf("\n\n\t22. Boot Signature.............: %u",b->BS_BootSig); // BYTE
printf("\n\n\t23. Volume ID..................: %lu",b->BS_VolID); // DWORD
printf("\n\n\t24. Volume Lable...............: %s",b->BS_VolLab); //for(int i=0;i<11;i++) printf("%c",b->BS_VolLab[i]); // BYTE [11]
printf("\n\n\t25. File System Type...........: "); for(int i=0;i<8;i++) printf("%c",b->BS_FilSysType[i]); // BYTE [8]
}
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef unsigned long long QWORD;
让我们制作一些足够可移植的东西,当发现它被用在假设不再成立的地方时,它会给我们一个编译器警告。
首先,我们需要看看这些类型是如何定义的。在我的 64 位机器上
// C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared\minwindef.h
typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef unsigned short WORD;
现在32位的情况如何?
根据此链接的 MSDN 页面,定义仍然相同,因此大小的差异来自于
long
等在 32 位 Windows 上具有不同大小的事实,而不是来自 DWORD 等的任何不同定义。他们自己。 https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types
因此,问题是,我们如何便携地打印
unsigned long
等? C99 给了我们几个答案。
首先,
中定义了
PRIxxx
printf
添加了有趣的长度修饰符。 https://en.cppreference.com/w/c/99
它们可以在 Visual Studio 中使用,假设您有足够新的版本。 https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specation-syntax-printf-and-wprintf-functions?view=msvc-170
z
size_t
及其签名版本t
ptrdiff_t
及其无符号版本j
intmax_t
和 uintmax_t
对于
WORD
,即unsigned short
,修饰符是h
,所以使用%hu
。
https://en.cppreference.com/w/c/io/fprintf
printf("\n\n\t3. Bytes per Sector...........: %hu",b->BPB_BytsPerSec); // WORD
当小于 int 的整数类型作为参数传递给可变参数函数(printf 就是)时,它会被提升为 int 或 unsigned int。所以,你可以像打印一个 int 一样打印一个 WORD。 https://en.cppreference.com/w/c/language/conversion
intmax
投射到
intmax_t
或 uintmax_t
,然后分别使用 %jd
或 %ju
。这每次都会有效,因为 intmax
是系统上最大的可能类型。 https://stackoverflow.com/a/3171743/1047788
printf("\n\n\t13. Number of Hidden Sectors...: %ju", (uintmax_t)b->BPB_HiddSec); // DWORD