(EDIT:MFC)CString类的对象的内部结构是什么

What is the internal structure of an object of the (EDIT: MFC) CString class?

本文关键字:对象 内部 结构 是什么 CString EDIT MFC      更新时间:2023-10-16

我需要(有效地)从(Edit:MFC)CString对象strncpy()到C字符串变量。众所周知,strncpy()有时无法正确终止dest C字符串(具体取决于源长度**EDIT和调用中指定的长度)。为了避免这种邪恶,我想在CString源对象中存储一个NUL字符,然后将其存储到strcpy()memmove()中。

这样做合理吗?如果是,我必须在CString对象内部操作什么?如果没有,那么有什么替代方案可以保证正确终止的目的地C字符串?

strncpy()仅在源字符串超过指定的长度限制时"失败"为null终止目标字符串。您可以通过自己将目的地的最后一个字符设置为null来确保目的地是null终止的。例如:

#define DEST_STR_LEN 10
char dest_str[DEST_STR_LEN + 1];  // +1 for the null
strncpy(dest_str, src_str, DEST_STR_LEN);
dest_str[DEST_STR_LEN] = '';

如果src_str的长度超过DEST_STR_LEN个字符,则dest_str将是一个正确终止的DEST_STR_LEN字符字符串。如果src_str比它短,strncpy()将在dest_str内的某个位置放置一个null终止符,因此最末端的null是不相关且无害的。

CSimpleStringT::GetString提供一个指向以null结尾的字符串的指针。以此作为strncpy的来源。由于这是C++,所以在与遗留API接口时应该只使用C样式字符串。请改用std::string

替代方法之一是先将字符串归零,然后从CString强制转换或memcpy。

我希望它们与我使用它们时没有改变:那是多年前的事了:)

他们使用了一个有趣的"技巧"来处理refcount和非常快速高效的自动转换为char*:即指针指向LPCSTR,但保留了一些后字节以保持实现状态。

因此,结构可以与旧的windows API(LPCSTR,无开销)一起使用。我当时觉得这个主意很有趣!

当然,关键是分配器的可用性:它们只是在mallocating/free时偏移指针。

我记得有一个缓冲区请求(例如)修改可用数据:GetBuffer(0),然后是ReleaseBuffer()。

HTH

如果您没有在启用_UNICODE的情况下进行编译,那么您可以很容易地从CString获得const char *。只需将其投射到LPCTSTR:

CString myString("stuff");
const char *byteString = (LPCTSTR)myString;

这保证是以NULL终止的。

如果使用_UNICODE构建,则CString是UTF-16编码的字符串。你真的不能直接用它做任何事情。

如果您确实需要从CString复制数据,这非常容易,即使使用C样式代码也是如此。只需确保您分配了足够的内存并复制了正确的长度:

CString myString("stuff");
char *outString = (char*)malloc(myString.Length() + 1);
strncpy(outString, (LPCTSTR)myString, myString.Length());

CString以NULL结尾,因此只要文本正确(内部没有NULL字符),复制就应该是安全的。你可以写:

char szStr[256];
strncpy(szStr, (LPCSTR) String, 3);
szStr[3]=''; /// b-cos no null-character is implicitly appended to the end of destination

如果在CString对象中存储null somehere,可能会给自己带来更多问题,CString会在内部存储其长度。

另一种替代解决方案更倾向于CPU或编译器的支持,因为这是一种更好的方法-只需确保在"安全"模式下复制内存时,在每次原子操作后的任何时候,末尾都会添加零,因此当整个循环失败时,目标字符串仍将终止,而无需在复制前将其完全清零。也可以支持快速清零——只需标记清零区域的开始和停止,它就会立即在RAM中清除,这会让事情变得容易得多。