在C语言中,为什么声明后无法将字符串赋值给字符数组?

14

这件事已经困扰我一段时间了。

struct person {
       char name[15];
       int age;
};
struct person me;
me.name = "nikol";

当我编译时,出现以下错误:

error: incompatible types when assigning to type ‘char[15]’ from type ‘char *’

我有什么明显的遗漏吗?


1
你是在问如何进行初始化吗?struct person me = {"nikol", 3}; 应该可以。 - William Pursell
为什么不能将相同类型和大小的数组赋值给另一个数组? - Ciro Santilli OurBigBook.com
免责声明:本回答请注意,这是一个程序设计相关的内容。 - Sourav Ghosh
6个回答

23

C 中的数组是二等公民,它们不支持赋值。

char x[] = "This is initialization, not assignment, thus ok.";

这行不通:

x = "Compilation-error here, tried to assign to an array.";

使用库函数或手动复制每个元素:

#include <string.h>
strcpy(x, "The library-solution to string-assignment.");

2
我混淆了初始化和赋值,很抱歉。是的,这解决了问题,谢谢。老师的一个例子把我引入了错误的方向(现在我看到它是错的)。 - Kok Nikol

9

me.name = "nikol";是错误的!!你需要使用strcpy()

当你执行x = "Some String"时,实际上是将静态字符串"Some String"的起始地址放入变量x中。在你的情况下,name是一个静态数组,你不能改变它的地址。你所需要的是将你的字符串复制到已分配的数组name中。为此,请使用strcpy()


3

首先,您需要知道以下几点:

  • 在 C 语言中,文本字符串只是数组。
  • 在 C 语言中,数组变量基本上只是指针。

因此,char mytext[12]; 实质上只是声明了一个 char 指针变量,名为 mytext,它存储了数组/字符串的第一个(零号)元素的地址。

因此,以下代码是有效的:

#include <stdio.h>
int main(int argc, char *argv[])
{
    const char a[] = "Hello";
    const char *b = a;
    printf("%s\n", b);
    return 0;
}

重要的是要注意,重新分配b并不会更改它指向的任何内容 - 它只是更改了它所指向的东西。
然而,在某些情况下,数组和指针的行为是不同的。在上面的例子中,a不能被重新分配。如果您尝试这样做,就会出错
回到您最初的例子,这个结构:
struct person{
    char name[15];
    int age;
};

...可以将其看作一个19字节的结构体*,其中前15个字节用于存储字符串。 name 属性存储第一个字节的地址,因此您知道这15个字节在内存中的位置 - 您只需要将一些有用的东西写入它们即可。

这就是诸如 sprintf()strcpy() 等函数发挥作用的地方 - 它们将数据复制到由 name 定义的地址中,而不是重新分配 name 本身。

* 当然,假设 sizeof(int) 是4且该结构没有填充...


1
示例结构体的大小为20字节。数组和整数之间有一个填充字节。 - mch
你说得没错 - 我会相应地编辑我的回答。 - GoBusto
其实,我第一次说的没错 - 它是19个字节不带填充,就像我最初说的那样。 - GoBusto
1
当你不能清楚地区分数组和指针时,你会开始遇到很糟糕的问题。在C语言中,字符串是以0结尾的序列。 - Deduplicator
1
@KokNikol:实际上,我指的是GoBusto,因为他的帖子并没有真正反映出这一点。是的,他后来提到了一个区别,但这太少了(还有更多),而且太晚了(他在开始时设定了基调,太多人会忽略这一点)。 - Deduplicator
显示剩余2条评论

0

首先,你必须了解数组中的内存分配方式。

当你声明一个数组的名称时,该名称实际上作为指针工作,并指向数组的第一个元素。

struct person {
       char name[15];
       int age;
};

这里的name指向数组的第一个元素即name[0]的内存地址。 你必须声明字符数组,以便每个内存块都有1字节的大小。而name也指向1字节的内存。

struct person me;
me.name = "nikol";

me.name = "nikol"; 这段代码不起作用。它将 5 字节的数据分配给了 1 字节的存储空间,并且没有对指针变量进行解引用。

为了更好地理解,请尝试以下代码:

struct person me;
*me.name = 'n';

在这里,我已经定义了指针name并分配了1个字节的数据。这段代码将完美地运行。

printf("%c" , me.name[0]);

输出将会是 n。

这就是为什么我们必须使用 strcpy() 函数。Strcpy() 函数会将字符串常量的每个字符分配给数组的每个内存块,因此它才能正常工作。

strcpy(me.name , "nikol");

-1

您正在尝试更改数组指针的内存地址(通过给 me.name 赋值 "nikol"),这是不可能的。数组的名称(me.name)是一个固定的指针,不能被更改为指向字符串("nikol")的新位置,因为数组指针的内存地址位于该数组的第一个成员上。如果您想在声明后分配一个字符串(me.name = "nikol"),请使用外部指针 *name,因为外部指针浮动在数组之外,所以它的值可以随时更改。

struct person {
       char *name;
       int age;
};
struct person me;
me.name = "nikol"; // no error

-1
使用string.h库中的strcpy()函数 :)
main(){
struct person{
       char name[15];
       int age;
};
struct person me;
strcpy(me.name,"nikol");
}

FYI:string.h是一个头文件,而不是一个库。 - pmg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接