C:如何以更简洁的方式将空终止符复制到结构成员?
本质上,我对一个字符串进行标记,并将找到的字符串strncpy
转换为结构成员,即 stringid。它当然存在缺乏终止的问题,我为它添加了一个额外的数组空间,我不知道如何正确添加它。
我是这样做的:
my_struct[iteration].stringID[ID_SIZE-1] = '\0' //updated
我不确定这是否真的有效,在我看来,它看起来很糟糕。
Str(n) 复制空字符或 0 会导致 GCC 和 MinGW 生成警告:
warning: null argument where non-null required (arg 2)
我是否不知道如何以干净的方式执行此操作?我正在考虑将成员数组设置为全零,然后复制字符串以很好地适应空终止。您有什么建议或做法吗?
Essentially I am tokenizing a string and strncpy
ing the string found to a structure member, i.e. stringid. It of course suffers from the problem of lack of termination, I have added an extra array space for it, I've no clue how to add it properly.
I had done it like so:
my_struct[iteration].stringID[ID_SIZE-1] = '\0' //updated
I am unsure if that really works, it looks horrible IMO.
Str(n)cpying a null character, or 0, results in a warning generated by GCC and MinGW:
warning: null argument where non-null required (arg 2)
Am I blind on how to do this in a clean manner? I was thinking of memsetting the member array to all zeros, and then copying the string in to nicely fit with null termination. Do you have any suggestions or practises?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
有两件事:
strncpy()
具有非常意外的语义,如果字符串未完全填充,它将始终填充 0 缓冲区,如果字符串完全填充缓冲区,则不会终止字符串。这两个都很奇怪,我建议不要使用它。stringID[ID_SIZE]
似乎正在做的那样;这是越界的。最好的解决方案是编写一个不太奇怪的自定义版本的
strncpy()
,或者(如果您知道输入的长度)只需使用strcpy()
。更新:如果输入标记的长度是静态的,但由于标记化过程,它们在源缓冲区中不是以 0 结尾,则只需使用
memcpy()
和手动终止:我认为没有必要将上面的内容“包装”在宏中。
Two things:
strncpy()
has very unexpected semantics, it will always 0-fill the buffer if not totally filled by the string, and it will not terminate the string if it completely fills the buffer. Both of these are weird enough that I recommend against using it.stringID[ID_SIZE]
seems to be doing; that is out of bounds.The best solution is to write a custom version of
strncpy()
that is less weird, or (if you know the length of the input) just usestrcpy()
.UPDATE: If the length of your input tokens is static, but they're not 0-terminated in the source buffer due to your tokenization process, then just use
memcpy()
and manual termination:I don't see a need to "wrap" the above in a macro.
实际上,按照您建议的方式进行 null 终止一点也不可怕,我个人非常喜欢它。
在我看来,最好的方法是以类似的方式将其定义为宏:
然后您可以在代码中随心所欲地使用它。
在 Windows 上,Microsoft 为您提供了以下在复制字符串时以 null 终止的函数: StringCchCopy
Actually, null terminating the way you suggested isn't horrible at all and I personally very much like it.
The best way, in my opinion, would be to define it as a macro in similar fashion:
Then you can use it all around your code as much as you want.
On Windows Microsoft gives you the following functions which null terminate when copying string: StringCchCopy
正如其他人所指出的,strncpy 具有奇怪的语义。进行有界字符串复制的惯用方法是
strncat
到一个空字符串上:这总是附加一个终止 NUL(并且最多填充 ID_SIZE 字符,包括 NUL)。
As others have noted,
strncpy
has odd semantics. The idiomatic way to do a bounded string copy is tostrncat
onto an empty string:This always appends a terminating NUL, (and fills at most ID_SIZE characters including the NUL).
我最终编写了一个 strncpyz(char* pszTo, char* pszTo, size_t lSize) 函数来强制 NULL 终止。如果您有一个库可以放入它,那么这会非常有效。使用它还需要最少的代码更改。
我不热衷于宏方法,因为有人会传递指向错误宏的指针。
I ended-up writing a strncpyz(char* pszTo, char* pszTo, size_t lSize) function that forces the NULL termination. This works pretty-well if you have a library to put it in. Using it also requires minimal code changes.
I'm not keen on the macro approach because somebody will pass a pointer to the wrong macro.