将 var 分配给 var —— 会起作用吗?
我正在尝试为我正在开发的包装器做一些有用的事情。我正在为 C 的标准字符串库编写一个包装器,因为我不喜欢它。
我现在不想将 C 字符串引入我的包装器中。我有一个名为“str”的结构,其中包含字符串的长度和缓冲区:
struct str
{
char *buf;
size_t len;
};
在我的头文件中,我有这个:
typedef struct str str;
现在我已经实现了封装(我认为)。
所以我这样声明字符串:
str *a_string = NULL;
我已经完成了我想做的所有事情,但我有一个问题。我想为一个函数添加这样的东西:
str.h:
extern str *str_str(str *, char *);
和str.c
str *str_str(str *buf, char *ns)
{
buf->len = strlen(ns);
buf->buf = (char *) malloc(buf->len + 1);
strncpy(buf->buf, ns, buf->len);
return buf;
}
并测试它效果很好:
str *s = str_new();
printf("%s\n", str_cstr(str_str(s, "hello")));
output: hello
但这会起作用吗?
str_assign(s, str_str(s, "ok"));
我认为,这本质上是将 s
分配给 s
。当我打印时,它什么也没打印!
我没有收到任何错误! 非常感谢所有帮助。我对 C 语言还很陌生。
str_assign()
的来源:
void str_assign(str *s1, str *s2)
{
s1->len = s2->len;
s1->buf = (char *) malloc(s2->len + 1);
strncpy(s1->buf, s2->buf, s2->len);
}
I am trying to do something useful for a wrapper I am working out. I am writing a wrapper for the standard string library for C because I don't like it.
I don't want to introduce C strings to my wrapper right now. Ihave a struct called `str which contains the string's length and the buffer:
struct str
{
char *buf;
size_t len;
};
In my header file I have this:
typedef struct str str;
Now I have implemented encapsulation (I think).
So I declare strings like this:
str *a_string = NULL;
I have already done everything that I want to do with this, but I have one problem. What I would like to add something like this for one function:
str.h:
extern str *str_str(str *, char *);
and str.c
str *str_str(str *buf, char *ns)
{
buf->len = strlen(ns);
buf->buf = (char *) malloc(buf->len + 1);
strncpy(buf->buf, ns, buf->len);
return buf;
}
and testing this works well:
str *s = str_new();
printf("%s\n", str_cstr(str_str(s, "hello")));
output: hello
but will this work?
str_assign(s, str_str(s, "ok"));
That's essentially assigning s
to s
, I think. When I print, it prints nothing!
I don't get any errors!
All help is greatly appreciated. I am fairly new with the C language.
Source of str_assign()
:
void str_assign(str *s1, str *s2)
{
s1->len = s2->len;
s1->buf = (char *) malloc(s2->len + 1);
strncpy(s1->buf, s2->buf, s2->len);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我知道这是 C,但将其与 C++ 进行比较很有用。当你用C++编写赋值运算符时,你总是必须考虑自赋值的情况。当您在 C 中执行相同的工作时,这同样适用。
因此,我认为您需要:
您可以使用 memcpy() ,因为 (a) 字符串保证是不相交的,并且 (b) 您知道字符串有多长,因此您不需要像使用
strncpy()
或strcpy()
那样在每一步检查字符串的结尾。实际上,有一种情况说你永远不需要使用
strcpy()
或strncpy()
或strcat()
或strncat ()
;您应该始终知道源字符串和目标字符串的长度(否则您无法确定不会出现缓冲区溢出),因此您始终可以使用memmove()
或memcpy() 代替。
我还注意到,在某些时候您将不得不担心内存泄漏。我刚刚修改了上面的分配以释放旧字符串,然后用新字符串覆盖它。
您还可以通过仅在新字符串比旧字符串长时分配新空间来优化操作。您也可以考虑使用
realloc()
而不是malloc()
。但是,您必须小心内存泄漏陷阱。这是使用realloc()
的错误方法:如果
realloc()
失败,您只是用 null 覆盖了您的点 - 丢失了您对旧空间。您应该始终将 realloc() 的结果存储在与第一个参数不同的变量中:您最终可能决定在结构中保留两个长度 - 分配的空间和使用的空间。然后,您可以更有效地重用空间,仅当新字符串比先前分配的空间长时才分配更多空间,但仍然允许您随时缩短字符串。
I know this is C, but it is useful to compare this with C++. When you write an assignment operator in C++, you always have to consider the case of self-assignment. The same applies when you do the equivalent job in C.
Therefore, I think you need:
You can use
memcpy()
because (a) the strings are guaranteed to be disjoint, and (b) you know how long the string is, so you don't need to check for the end of string at each step of the way as you would withstrncpy()
orstrcpy()
.Actually, there's a case for saying you should never need to use
strcpy()
orstrncpy()
orstrcat()
orstrncat()
; you should always know how long the source and destination strings are (otherwise you can't be sure that there won't be a buffer overflow), so you can always usememmove()
ormemcpy()
instead.I also note that you're going to have to worry about memory leaks at some point. I just amended the assignment above to release the old string before overwriting it with the new.
You could also optimize operations by only allocating new space when the new string is longer than the old. You could consider using
realloc()
instead ofmalloc()
, too. However, you must be careful of the memory leak trap. This is the wrong way to userealloc()
:If
realloc()
fails, you've just overwritten your point with a null - losing the only reference you had to the old space. You should always store the result ofrealloc()
in a different variable from the first argument:You might eventually decide to keep two lengths in your structure - the space allocated and the space used. Then you can reuse space more efficiently, only allocating more space when the new string is longer than the previously allocated space, but still allowing you to shorten a string at any time.
您需要在
str_str
函数中包含 return 语句,因此添加return buf;
。如果您稍微考虑一下,您会发现
str_assign
函数中存在一个错误,因为在更改s1->buf
指针后,您实际上正在更改s2->buf
也是因为它们指向相同的结构。这是一个应该更适合您的实现:You need to have a return statement in your
str_str
function, so addreturn buf;
.If you think about it a little bit you will see there is a bug in your
str_assign
function because after you change thes1->buf
pointer you are actually changings2->buf
also because they point to the same struct. Here is an implementation that should work better for you:我在以下代码中看到
内存泄漏
!如果
s1
和s2
指向相同的内存位置,那么您将使用malloc
分配新内存并将其分配给已经存在的指针指向有效的内存位置并包含有效的 struct str 数据! ..可以通过执行以下操作进行简单检查来避免这种情况I see a
memory leak
in the following code!if
s1
ands2
point to the same memory location, then you're allocating new memory usingmalloc
and assigning it to the pointer which is already pointing to a valid memory location and containing a validstruct str
data! .. this can be avoided by putting a simple check by doing the following