#include <stdio.h>
#include <string.h>
struct car {
char make[10];
char model[25];
char type[10];
};
void main()
{
struct car myCar;
strcpy(myCar.make, "Nissan");
strcpy(myCar.model, "Rogue");
strcpy(myCar.type, "SUV");
//char make[] = myCar.make;
//char model[] = myCar.model;
//char type[] = myCar.type;
}
字符集
我试图将myCar.make的值赋给make[]。为什么我不能直接将myCar.make的值赋给make[]?
注:我主要用java编程,那么这个问题和我对java的理解有关系吗?
4条答案
按热度按时间6mzjoqzu1#
考虑另一个同样不起作用的案例:
字符集
这里的情况与上面的代码相同,但更简单。
我同意,这 * 应该 * 工作。编译器 * 应该 * 能够指出
src
的大小为6(不要忘记空终止符)。所以dst
* 的大小应该是6,赋值应该一个字符一个字符地复制。然而,事实并非如此。你问我为什么。答案基本上是,当C被发明时,编译器的标准要低得多,所以除了一些特殊情况(比如当你首先定义
src
时),语言并不是这样工作的。我承认这可能不令人满意。当你写上面的代码时,编译器基本上会看到:
型
这种现象被称为“指针衰减”,更常见的情况是函数参数。希望你能明白为什么把指针复制到数组中不起作用:
dst
在堆栈上分配。编译器如何知道要提前分配多少堆栈空间?它不能;它必须等到运行时才能看到字符串src
指向什么大小,到那时就太晚了。现代编译器更好,他们意识到了这个问题:
型
简而言之,它理解
src
是一个数组,但60年代和70年代制定的语言规则不允许它推断大小。另一种看待这一点的方式是,这种语言不够智能,无法理解更复杂的赋值。逐个字符赋值(
strcpy
的核心)实际上是一个不平凡的操作。C语言的规则是只能复制已知大小的东西,比如int
s、指针和struct
s。数组的大小不是它的类型的一部分,在C中,所以一个数组和另一个数组有不同的大小,不能赋值。我用“in C”来限定所有这些,因为C仍然与历史上的原始语言非常相似。有些人认为这种简单是值得尊敬和可取的。其他人则认为这是毫无意义的限制--缺乏表现力,没有任何意义。
C++继承了C的规则,但也提供了
std::string
,它可以理解operator=
(实际上在这种情况下是一个构造函数),足以复制:型
当你得到
dst
的定义时,编译器仍然将src
视为指针,但是std::string
有一个理解指针的构造函数,并且会做正确的事情:用strlen
发现指向的字符缓冲区的长度,动态分配新的内存来保存它,并逐个字符地复制它。数组也可以定义为size is 是类型的一部分:
型
当然,现在出于同样的原因,我们不能用
"hello"
初始化src
。……wgeznvg72#
我试图将myCar.make的值赋给make[]。为什么我不能直接将myCar.make的值赋给make[]?
字符集
这更好地称为“初始化”而不是“赋值”。虽然有相似之处,但C对 * 初始化 * 和 * 赋值 * 有不同的规则。初始化发生在对象被 * 定义 * 并**给定一个值时。
不幸的是,在这种情况下,array
myCar.make
首先被转换为第一个元素的类型和地址,因此代码如下所示:型
试图用指针初始化数组-这是没有意义的。
C没有提供一种通过简单的初始化来初始化数组(并确定其大小)的方法。
另一种方法是定义一个新数组,初始化或不初始化,然后 * 赋值 * 数组元素。
型
一种更符合C语言习惯的方法涉及字符串管理。这可能比OP现在准备的更先进。
型
qv7cva1a3#
在C中,你不能像使用常规变量那样直接用一个数组初始化另一个数组,因为数组在C中不是直接可赋值或可初始化的类型。
初始化发生在声明时,而赋值发生在声明变量之后。
当你声明一个像char make[]这样的数组时,编译器需要在编译时知道数组的大小,这样它才能分配正确的内存量。
当您尝试执行char make[] = myCar.make;你实际上是在用指针初始化数组。
赋值的右边(myCar.make)是一个表达式,没有与之关联的内存分配。
你必须一个元素一个元素地复制数组,这可以使用strcpy()这样的函数来完成。
以下是如何修改代码:
字符集
在这段代码中,为make、model和type声明了与car结构中的字符串大小相同的新字符串。
然后使用strcpy()将myCar.make、myCar.model和myCar.type的内容复制为make、model和type。
js5cn81o4#
您正在尝试声明新的字符数组,并将myCar.make、myCar.model和myCar.type的值赋给它们,对吗?但有个问题在C中,数组(包括那些存储字符串的数组,也称为字符数组)比简单的数据类型要复杂一些。它们对赋值运算符(=)不友好。
所以,当你说char make[] = myCar.make;,C编译器听到的是“嘿,创建一个新数组,并将myCar.make的内容复制到其中!但是编译器说“不行,伙计。我并不适合只使用=来处理复制数组。对不起!”
相反,您必须使用类似strcpy()函数的东西,类似于您在为myCar.make、myCar.model和myCar. type赋值时所做的操作。
字符集
将make、model和type声明为具有适当大小的字符数组(与结构体中的大小相同),然后将相应结构体成员的内容复制到其中。
我的电脑不在我身边,我不能检查我的代码,这是真的很长一段时间,我没有用C程序。