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

时间:2012-02-25 16:52:52

标签: c++ mfc format cstring

我需要{(1)}(有效地)从(编辑:MFC)CString对象到C字符串变量。众所周知,strncpy()有时会失败(取决于源长度** EDIT 和调用中指定的长度)来正确终止dest C字符串。为了避免这种恶意,我想将NUL字符存储在CString源对象中,然后存储到那个人的strncpy()strcpy()

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

7 个答案:

答案 0 :(得分:1)

CSimpleStringT::GetString给出一个指向以null结尾的字符串的指针。将此作为strncpy的来源。由于这是C ++,因此在与旧版API交互时只应使用C风格的字符串。请改用std::string

答案 1 :(得分:1)

我希望他们从使用它们时不会改变:那是多年前的事情:)

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

因此,结构可以使用与旧的Windows API(LPCSTR没有开销)。我当时发现这个想法很有意思!

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

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

HTH

答案 2 :(得分:1)

当源字符串长于您指定的长度限制时,

strncpy()仅“失败”以空终止目标字符串。您可以通过将其最后一个字符设置为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] = '\0';

如果src_str长度超过DEST_STR_LEN个字符,则dest_str将是一个正确终止的DEST_STR_LEN字符字符串。如果src_strstrncpy()短,dest_str会在{{1}}内的某处放置一个空终止符,因此最后的空值无关紧要且无害。

答案 3 :(得分:1)

其中一种替代方法是首先将字符串置零,然后从CString中转换或memcpy。

答案 4 :(得分:1)

如果您未在启用_UNICODE的情况下进行编译,那么您可以非常轻松地从const char *获得CString。只需将其投放到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());

答案 5 :(得分:1)

CString以NULL结尾,只要你的文本正确(里面没有NULL字符),那么复制应该是安全的。你可以写:

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

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

答案 6 :(得分:0)

另一种替代解决方案宁愿涉及来自CPU或编译器的支持,因为它是更好的方法 - 只需确保在“安全”模式下复制内存时,在每次原子操作之后的任何时间都会在最后添加零,所以当整个循环失败时,目标字符串仍将被终止,而不需要在复制之前将其完全归零。 也可以支持快速零 - 只需标记零点区域的开始和停止,它就会立即在RAM中清除,这会使事情变得更容易。