我想知道为什么第一个语句有效,为什么第二个语句在 C++ 中不起作用
char a[10]="iqbal"; // it works
a="iqbal"; // does not work
严格来说,数组不是指针! 并且数组(数组的基地址)不能是可修改的左值。即它不能出现在赋值运算符的左侧。数组仅在某些情况下才会衰减为指针。阅读这篇SO post以了解数组何时衰减为指针。这是另一篇好文章,它解释了数组和指针之间的区别
另请阅读有关左值和右值的内容这里,以便您了解无法出现在
=
的 LHS 上的事物
char a[10]="iqbal"; // 它有效
在这种情况下,内部发生的事情是
a[0] = 'i';
a[1] = 'q';
.
.
a[5] = '\0';
所以一切都很好,因为
array[i]
是一个可修改的左值。
a=“iqbal”; // 不起作用
在内部,这大致相当于
0x60000(Address of a, but is a simple number here ) = Address of "iqbal"
这是错误的,因为我们无法将某些内容分配给数字。
如果像这样初始化,则字符数组 a 将是静态的并且无法更改。无论如何,你永远不能在c中分配字符串a =“iqbal”。为此,您必须使用 strncpy 或 memcpy。否则,您将尝试覆盖指向字符串的指针,而这不是您想要的。
所以正确的代码会执行以下操作:
char a[10];
strncpy(a, "iqbal", sizeof(a) - 1);
a[sizeof(a) - 1] = 0;
-1是为终止零保留一个字节。请注意,您必须自己检查字符串是否以 null 结尾。糟糕的 API。有一个 strlcpy() 调用可以为您执行此操作,但它不包含在 glibc 中。
第一行不是语句,而是带有初始化的声明。 第二行是带有赋值运算符的表达式语句。
不能在 C 中分配数组。
但是您可以使用字符串文字的元素初始化数组。
为什么第一个语句有效,为什么第二个语句在 C++ 中不起作用
因为它们是不同的陈述,几乎完全无关。不要对它们都使用
=
符号这一事实感到困惑。在一种情况下,它代表对象初始化。在另一种情况下,赋值运算符。
您的第一行是合法的,因为初始化聚合(包括字符数组)是合法的。
你的第二行不合法,因为分配给数组是不合法的。
既然这是 C++,我可以建议你避免使用裸数组吗?对于字符串,请使用
std::string
。对于其他数组,请使用 std::vector
。如果你这样做,你的例子就会变成:
std::string a = "iqbal"; // it works
a="iqbal"; // so does this
在声明后,您不能将字符串文字分配给 char 数组。
一个很好、简单且有效的替代方法是使用
std::strcpy
来执行此操作,如下所示:
struct S
{
char name[30];
};
S s;
std::strcpy( s.name,
"The moribunds salute you." );
写作时 字符 a[10]="iqbal" 您正在使用字符初始化字符数组 a 的元素。我们可以对 int 类型执行相同的操作(请注意,char 类型的处理方式略有不同): int a[10]={1,2,...};
但是在声明部分之后编写以下内容将是无效的,因为 a 将被视为指针。所以写一些类似的东西 a={1,2,...}; 或a=“iqbal” 没有任何意义!
尝试:
char a[10]="iqbal";
char *my_a = a;
并与 my_a 一起工作。
在 C++11 中,你可以使用 lambda 来进行初始化,如下所示:
bool test = true;
/*const*/ char a[10] = { //Aggregate initialization
[=] //capture by value
()//no parameters
{ //start lambda
switch (test) {
case true: return *"test=true"; //*"xxx" don't return a pointer, but the 'string' itself
case false: return *"test=false";
} //switch
}()}; //}, close the lambda, (), call it, }; close aggregate initialization
当您的环境不支持
std::string
(例如 NVidia 的 CUDA 或一些奇怪的嵌入式环境)时,这会派上用场。
lambda 被内联,因此在内部它会转换为 char a[10] = test?"xxx":"yyy";
如果您可以选择这样做,那么您显然希望始终使用
std::string
,因为固定大小的字符缓冲区从根本上来说是一个坏主意。
如果您使用
std::string
,您可以使用:chararray = mystring.c_str();
将其转换为字符数组。如果您坚持使用printf
,这很有用:printf("s = %s", mystring.c_str());
。
strncpy_s() 适用于 CPP;
char dst[7];
strncpy_s(dst, 7, "Hello, world!", 6);
// above can also be
strncpy_s(dst, 7, "Hello, world!", _TRUNCATE);