字节数与字符数

时间:2011-01-28 05:21:33

标签: c windows string api api-design

某些api需要计数字符。

// Why did they choose cch in these functions.
HRESULT StringCchCopyW(
  __out  LPWSTR pszDest,
  __in   size_t cchDest,
  __in   LPCWSTR pszSrc
);

errno_t wcscpy_s(
   wchar_t *strDestination,
   size_t numberOfElements,
   const wchar_t *strSource 
);

DWORD WINAPI GetCurrentDirectoryW(
  __in   DWORD nBufferLength, // Count of Chars
  __out  LPWSTR lpBuffer
);  

有些api需要字节数。

// What do you prefer cch vs cb function.
// Do cch functions almost useful?
HRESULT StringCbCopyW(
  __out  LPWSTR pszDest,
  __in   size_t cbDest,
  __in   LPCWSTR pszSrc
);

BOOL WINAPI ReadFile(
  __in         HANDLE hFile,
  __out        LPVOID lpBuffer,
  __in         DWORD nNumberOfBytesToRead,
  __out_opt    LPDWORD lpNumberOfBytesRead,
  __inout_opt  LPOVERLAPPED lpOverlapped
);

// Why did they choose cb in these structures.
// Because there are some apis uses cb, I always should see MSDN.
typedef struct _LSA_UNICODE_STRING {
  USHORT Length; // Count of bytes.
  USHORT MaximumLength; // Count of bytes.
  PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _FILE_RENAME_INFO {
  BOOL   ReplaceIfExists;
  HANDLE RootDirectory;
  DWORD  FileNameLength; // Count of bytes.
  WCHAR  FileName[1];
} FILE_RENAME_INFO, *PFILE_RENAME_INFO;

设计函数或数据结构时,如何确定cb或cch?为什么呢? 为了给呼叫者设计更好的api,我应该知道什么呢?

2 个答案:

答案 0 :(得分:3)

如果返回的数据是字符串,则应返回字符数,因为字节数通常是无用的。但如果它是通用二进制数据(而不是特定的字符串),那么显然字符数没有任何意义,所以使用字节数。

至于原因:

我认为LSA_UNICODE_STRING保持字节数的原因是它与UNICODE_STRING兼容,后者又用于NtCreateFile。但NtCreateFile接收FILE_OPEN_BY_FILE_ID参数,该参数实际上将UNICODE_STRING视为指向LONGLONG值,而表示字符串...所以字节数在那里更有意义,虽然我说它总体上是一个糟糕的设计:

  

FILE_OPEN_BY_FILE_ID:ObjectAttributes参数指定的文件名包含文件的8字节文件引用号。

答案 1 :(得分:0)

如果你注意到,你提到的第一组函数都是ASCII函数,因此在这种情况下没有区别 - 字节数是字符数。这是因为(通常,无论如何)单个ASCII字符的大小恰好是一个字节。

第二组是unicode函数/结构。在这种情况下,字符不能保证只有一个字节大小 - 如果是UTF16格式,它们将是两个字节宽,在UTF32中它们将是四个,而在UTF8中,它们(通常)可以是任何地方一到四个字节宽。

特别是对于UTF8数据的情况,如果你创建一个缓冲区,通常你会留出一定数量的字节,这取决于字符大小在字符数方面可能有很多种长度。我对你提出的大多数功能/结构都不太熟悉,但如果它与它有关,我也不会感到惊讶。

要回答你的问题,如果你正在使用ASCII,你可以使用任何一种方法 - 它没有任何区别。但是,如果使用可变长度编码(例如UTF8),是否使用其中一种编码取决于您是否只对所涉及的字符感兴趣,或者是否还需要考虑它们的编码。