简体   繁体   English

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

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

I need to strncpy() (effectively) from a ( Edit: MFC) CString object to a C string variable. 我需要strncpy() (有效)从( 编辑:MFC)CString对象到C字符串变量。 It's well known that strncpy() sometimes fails (depending on the source length **EDIT and the length specified in the call) to terminate the dest C string correctly. 众所周知, strncpy()有时会失败(取决于源长度** EDIT和调用中指定的长度),无法正确终止dest C字符串。 To avoid that evil, I'm thinking to store a NUL char inside the CString source object and then to strcpy() or memmove() that guy. 为了避免这种恶行,我正在考虑将一个NUL字符存储在CString源对象中,然后将该家伙存储在strcpy()memmove()中。

Is this a reasonable way to go about it? 这是合理的解决方法吗? If so, what must I manipulate inside the CString object? 如果是这样,我必须在CString对象内部进行哪些操作? If not, then what's an alternative that will guarantee a properly-terminated destination C string? 如果没有,那么有什么替代方法可以保证目标C字符串正确终止?

CSimpleStringT::GetString gives a pointer to a null-terminated string. CSimpleStringT :: GetString提供了一个指向以空字符结尾的字符串的指针。 Use this as the soure for strncpy . 使用它作为strncpy As this is C++, you should only use C-style strings when interfacing with legacy APIs. 由于这是C ++,因此在与旧版API进行接口连接时,仅应使用C样式的字符串。 Use std::string instead. 使用std::string代替。

I hope they don't changed from when I used them: that was many years ago :) 我希望它们从我使用时起就不会改变:那是很多年前的:)

They used an interesting 'trick' to handle the refcount and the very fast and efficient automatic conversion to char*: ie the pointer is to LPCSTR, but some back byte is reserved to keep the implementation state. 他们用一个有趣的“伎俩”来处理引用计数和非常快速,高效的自动转换为char *:即指针是LPCSTR,但一些回来字节被保留,以保持执行状态。

So the struct can be used with the older windows API (LPCSTR without overhead). 因此,结构可以用旧版Windows API(LPCSTR无开销)中使用 I found at the time the idea interesting! 当时我发现这个主意很有趣!

Of course the key ìs the availability of allocators: they simply offsets the pointer when mallocing/freeing. 当然,关键是分配器的可用性:它们在进行分配/释放时仅使指针偏移。

I remember there was a buffer request to (for instance) modify the data available: GetBuffer(0), followed by ReleaseBuffer(). 记得有一个缓冲请求 (例如)修改可用的数据:的GetBuffer(0),随后ReleaseBuffer()。

HTH 高温超导

strncpy() only "fails" to null-terminate the destination string when the source string is longer than the length limit you specify. 当源字符串长于您指定的长度限制时, strncpy()仅“失败”以终止目标字符串。 You can ensure that the destination is null-terminated by setting its last character to null yourself. 您可以确保目标是通过设置它的最后一个字符为空自己空值终止。 For example: 例如:

#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';

If src_str is more than DEST_STR_LEN characters long, dest_str will be a properly-terminated string of DEST_STR_LEN characters. 如果src_str不止DEST_STR_LEN字符长, dest_str将是一个正确结尾的字符串DEST_STR_LEN字符。 If src_str is shorter than that, strncpy() will put a null terminator somewhere within dest_str , so the null at the very end is irrelevant and harmless. 如果src_strsrc_str ,则strncpy()会将空终止符放在dest_str内的某个dest_str ,因此,最后的空无关紧要且无害。

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

If you are not compiling with _UNICODE enabled, then you can get a const char * from a CString very easily. 如果未在启用_UNICODE进行编译,则可以非常轻松地从CString获取const char * Just cast it to an LPCTSTR : 只需将其转换为LPCTSTR

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

This is guaranteed to be NULL-terminated. 保证以NULL结尾。

If you have built with _UNICODE , then CString is a UTF-16 encoded string. 如果你已经有内置_UNICODE ,然后CString是UTF-16编码字符串。 You can't really do anything directly with that. 您真的不能直接做任何事情。

If you do need to copy the data from the CString , this very easy, even using C-style code. 如果确实需要从CString复制数据,即使使用C样式代码,这也非常容易。 Just make sure that you allocate sufficient memory and are copying the right length: 只要确保分配足够的内存并复制正确的长度即可:

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

CString ends with NULL so as long as your text is correct (no NULL characters inside) then copying should be safe. CString以NULL结尾,只要您的文本正确(内部没有NULL字符),那么复制就应该是安全的。 You can write: 你可以写:

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

if you store null somehere inside CString object you will probably cause yourself more problems, CString stores its lenght internally. 如果你存储空somehere里面CString的对象,有可能会导致自己更多的问题,CString的内部存储的lenght。

Another alternative solution would rather involve support from CPU or compiler, as it's much better approach - simply make sure that when copying memory in "safe" mode, at any time after every atomic operation there is zero added on the end, so when whole loop fails, the destination string will still be terminated, without need to zero it fully before making copy. 另一个替代解决方案可能会涉及CPU或编译器的支持,因为这是更好的方法-只需确保以“安全”模式复制内存时,在每次原子操作之后的任何时间末尾都添加零,因此在整个循环时失败,目标字符串将仍然终止,而无需在复制之前将其完全清零。 There could be also support for fast zero - just mark start and stop of zeroed region and it's instantly cleared in RAM, this would make things a lot easier. 还可能支持快速归零-只需标记归零区域的开始和停止,它会立即在RAM中清除,这将使事情变得容易得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM