如何正确分配新的字符串值?
我试图以最清洁/最安全的方式了解如何在C中解决这个琐碎的问题。这是我的示例:
#include <stdio.h>
int main(int argc, char *argv[])
{
typedef struct
{
char name[20];
char surname[20];
int unsigned age;
} person;
// Here I can pass strings as values...how does it work?
person p = {"John", "Doe", 30};
printf("Name: %s; Age: %d\n", p.name, p.age);
// This works as expected...
p.age = 25;
//...but the same approach doesn't work with a string
p.name = "Jane";
printf("Name: %s; Age: %d\n", p.name, p.age);
return 1;
}
编译器的错误是:
main.c:在功能'main':main.c:18: 错误:不兼容的类型 从类型分配给'char [20]' 'char *'
我知道C(不是C ++)没有字符串类型,而是使用char
s的数组char
s:
#include <stdio.h>
int main(int argc, char *argv[])
{
typedef struct
{
char *name;
char *surname;
int unsigned age;
} person;
person p = {"John", "Doe", 30};
printf("Name: %s; Age: %d\n", p.name, p.age);
p.age = 25;
p.name = "Jane";
printf("Name: %s; Age: %d\n", p.name, p.age);
return 1;
}
这是按预期工作的,但是我想知道是否有更好的方法可以做到这一点。
I'm trying to understand how to solve this trivial problem in C, in the cleanest/safest way. Here's my example:
#include <stdio.h>
int main(int argc, char *argv[])
{
typedef struct
{
char name[20];
char surname[20];
int unsigned age;
} person;
// Here I can pass strings as values...how does it work?
person p = {"John", "Doe", 30};
printf("Name: %s; Age: %d\n", p.name, p.age);
// This works as expected...
p.age = 25;
//...but the same approach doesn't work with a string
p.name = "Jane";
printf("Name: %s; Age: %d\n", p.name, p.age);
return 1;
}
The compiler's error is:
main.c: In function ‘main’: main.c:18:
error: incompatible types when
assigning to type ‘char[20]’ from type
‘char *’
I understand that C (not C++) doesn't have a String type and instead uses arrays of char
s, so another way to do this was to alter the example struct to hold pointers of char
s:
#include <stdio.h>
int main(int argc, char *argv[])
{
typedef struct
{
char *name;
char *surname;
int unsigned age;
} person;
person p = {"John", "Doe", 30};
printf("Name: %s; Age: %d\n", p.name, p.age);
p.age = 25;
p.name = "Jane";
printf("Name: %s; Age: %d\n", p.name, p.age);
return 1;
}
This works as expected, but I wonder if there a better way to do this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
第一个示例不起作用,因为您无法将值分配给数组 - 数组在这方面像const指针一样工作。但是,您可以做的是将新值复制到数组中:
如果您知道先前知道字符串的最大尺寸,例如,在第一个示例中,您可以使用100%的名称适合19个字符(不是20个字符,总是需要一个字符来存储终止零值)。
相反,如果您不知道字符串的最大尺寸和/或要优化内存使用情况,则指针会更好,例如,避免保留512个字符以“ John”的名称。但是,使用指针,您需要动态分配它们指向的缓冲区,并在不再需要时将其释放,以避免内存泄漏。
更新:动态分配的缓冲区的示例(使用第二个示例中的结构定义):
The first example doesn't work because you can't assign values to arrays - arrays work (sort of) like const pointers in this respect. What you can do though is copy a new value into the array:
Char arrays are fine to use if you know the maximum size of the string in advance, e.g. in the first example you are 100% sure that the name will fit into 19 characters (not 20 because one character is always needed to store the terminating zero value).
Conversely, pointers are better if you don't know the possible maximum size of your string, and/or you want to optimize your memory usage, e.g. avoid reserving 512 characters for the name "John". However, with pointers you need to dynamically allocate the buffer they point to, and free it when not needed anymore, to avoid memory leaks.
Update: example of dynamically allocated buffers (using the struct definition in your 2nd example):
将字符串视为抽象对象,将字符阵列作为容器。字符串可以是任何尺寸,但容器必须比字符串长度(以保持空终止符)至少高1个。
C对字符串几乎没有句法支持。没有字符串操作员(仅是Char-Array和Char-Pointer Operators)。您无法分配字符串。
但是您可以调用功能以帮助实现所需的目标。
strncpy()
函数可以在此处使用。为了最大程度的安全性,我建议遵循此模式:还请查看
strncat()
和memcpy()
函数。Think of strings as abstract objects, and char arrays as containers. The string can be any size but the container must be at least 1 more than the string length (to hold the null terminator).
C has very little syntactical support for strings. There are no string operators (only char-array and char-pointer operators). You can't assign strings.
But you can call functions to help achieve what you want.
The
strncpy()
function could be used here. For maximum safety I suggest following this pattern:Also have a look at the
strncat()
andmemcpy()
functions.这两个结构是不同的。当您初始化第一个结构时,分配了大约40个字节的内存。当您初始化第二个结构时,分配了大约10个字节。 (实际数量是架构取决于)
您可以使用字符串文字(字符串常数)将字符数组杀死。这就是原因
在第一个示例中工作。
您无法(从常规意义上)分配C中的字符串C。
当您的代码执行时,您拥有的字符串文字(“ John”)被加载到内存中。当您用其中一种文字初始化数组时,将字符串复制到新的内存位置中。在第二个示例中,您只是将指针复制到字符串字面的位置。做类似的事情:
可能导致编译或运行时错误(我不确定。)这是一个坏主意,因为您正在修改字符串“ Hello”,例如,在微控制器上,它可以位于只读的内存中。
The two structs are different. When you initialize the first struct, about 40 bytes of memory are allocated. When you initialize the second struct, about 10 bytesof memory are allocated. (Actual amount is architecture dependent)
You can use the string literals (string constants) to initalize character arrays. This is why
works in the first example.
You cannot assign (in the conventional sense) a string in C.
The string literals you have ("John") are loaded into memory when your code executes. When you initialize an array with one of these literals, then the string is copied into a new memory location. In your second example, you are merely copying the pointer to (location of) the string literal. Doing something like:
might cause compile or runtime errors (I am not sure.) It is a bad idea because you are modifying the literal string "Hello" which, for example on a microcontroler, could be located in read-only memory.
第一个结构是字符数组[],第二个结构是字符串的指针 *(64位机器的大小8字节)。 According to Stephen Kochan's book "Programming in C", the only time that C lets you assign a constant string is when defining and initializing a char array as in
not even with
In the case of char *name;名称是角色指针,而不是数组。 When you did
it points to another string object.
output:
However, in the character array [] case, after you do
to change its content, the address of the buffer p.name[] never changes.
C和Python之间的一个有趣的相似之处是
Python的字符串是不变的,与C的字符串指针相似
字符串文字是只读的。
Python的列表是可变的,类似于C的角色阵列。
The first struct is a character array [] and the second struct is a pointer * to the character string (size 8 bytes for a 64-bit machine). According to Stephen Kochan's book "Programming in C", the only time that C lets you assign a constant string is when defining and initializing a char array as in
not even with
In the case of char *name; name is a character pointer, not an array. When you did
it points to another string object.
output:
However, in the character array [] case, after you do
to change its content, the address of the buffer p.name[] never changes.
An interesting parallel between C and Python is that
Python's String is immutable and is similar to C's string pointer where
string literals are read-only.
Python's List is mutable and is similar to C's character array.
在这两种情况下,您都在编写:
p.name
是一个数组,在第二种情况下 ,p.Name
是char*
,可以分配给字符串文字,因为字符串文字是char> char
的数组(数组可转换为指针),您可以使用诸如<<<<代码> strcpy ,
memcpy
et al。如其他响应中所示,但是您还可以通过分配整个struct
来规避此问题。实际上,将字符串作为
char*
和size_t
捆绑在一起很有用出色地。In both cases, you are writing:
p.name
is an array, and it's not possible to assign arrays in Cp.name
is achar*
, and those can be assigned to string literals, because string literals are arrays ofchar
(arrays are convertible to pointers)You can use functions such as
strcpy
,memcpy
et al. as shown in other responses, but you can also circumvent this issue by assigning the wholestruct
.In practice, it is useful to bundle strings as a
char*
andsize_t
in onestruct
, so this can often be done for individual strings as well.这是如何实现安全字符串分配的示例。如果字符串长于目标数组,则断言失败并且程序退出。
Here is an example of how to implement safe string assignment. If a string is longer than the target array, an assertion fails and the program quits.