为啥不能像这样复制char数组 charArray="some string";

Posted

技术标签:

【中文标题】为啥不能像这样复制char数组 charArray="some string";【英文标题】:why char array cant be copied like this charArray="some string";为什么不能像这样复制char数组 charArray="some string"; 【发布时间】:2014-07-12 10:48:02 【问题描述】:

为什么我们需要使用strcpy() 将字符串复制到 char 数组中?

我在这方面浪费了 2 个小时。它没有显示任何错误,但输出与我预期的不一样,我花了 2 个小时才找出错误。

它只是显示一个垃圾字符。

当我使用strcpy() 时,它工作正常。

【问题讨论】:

何不使用std::string,把烦恼抛在脑后 是的,我使用了 std::string,但我的项目有一些遗留的 c 代码,我再次必须将此字符串转换为 char。 你需要一个“C-string”吗?这就是std::string::c_str() 的用途。 是的,将其转换为 c char 数组需要使用 c_str();但我的问题是为什么我们不能只使用 = 运算符复制字符串。 这一定是个骗子。 【参考方案1】:

对答案的另一种解释是 char 数组是一种基本类型,而不是 operator = 被覆盖的类。

正如@StianV.Svendenborg 所提到的,将一个 char 数组分配给另一个意味着将其地址分配给另一个 char 指针变量。

char数组分配如;

char test[4]=1,2,3,4;

将分配 4 个字节(每个字节对应一个 char 值)。

在诸如算术之类的表达式中,test 的行为类似于指针。例如,test+1 将指向第二个元素的地址,*(test+1) == 2 将为真,并且 print("%p",test) 将打印数组中第一个元素的地址。

如果您使用std::stringoperator= 类,函数将遍历所有这些分配的字段并复制它们而无需您考虑。

【讨论】:

我试图解释这种行为。 你不需要为了解释行为而陈述虚假的事情,就好像它们是事实一样。 @BenjaminLindley 你是对的。这个表格正确吗?还是我应该删除答案? 我猜它稍微好一点。虽然它仍然有点误导。 test 并不总是表现为指针。例如,在获取其地址或大小,或绑定对它的引用时。最好说在某些表达式中,数组被转换为指向其第一个元素的指针。 @BenjaminLindley 更新了您的反馈。谢谢。【参考方案2】:

长答案:

一旦您在 C++ 中声明了任何数组,无论该数组是否为 int, char or MyClass 数组,对该数组名称的任何使用都与使用指向数组中第一个元素的指针基本相同。一旦动态分配数组,这一点就变得非常明显,但静态分配的数组也是如此。

也就是说下面的代码:

char arr[] = "Lorum ipsum";

意思是:

在堆栈上为 12 个字符分配足够的空间,并让 arr 表现为指向第一个字符的指针,这个指针是 const (即指向的内容不能更改。)

因此,如果您尝试编写:

const char * arr2 = "hello";
arr = arr2; // Error

您真正要问的是:将行为类似于无法更改的指针的arr 更改为现在指向此常量字符串中的第一个字符。这是不允许的。

话虽如此,如果您改为使用指向常量字符串的指针,则可以使用所描述的语法:

const char * cstr1 = "Hello";
const char * cstr2 = "Bye";
cstr1 = cstr2;          // All is good, you are only changing which 
                        // c-string in the global data you are pointing to.

【讨论】:

【参考方案3】:

简答: 这是因为数组是静态分配内存的,您无法重新初始化它们。 数组的大小是固定的。 相反,您可以使用std::string

不过,您可以像这样使用char* 指针。

【讨论】:

【参考方案4】:

简答: 为了效率。对于不希望数组被复制的人。

当您使用原始指针时,您需要考虑所有这些细节,例如内存管理、复制行为等,以实现您自己的性能要求。否则,您可以使用std::string,它旨在满足大多数正常情况。

【讨论】:

【参考方案5】:

所谓的 C 字符串起源于 C 语言,它不具备用于字符串处理的高级语言功能。这里有两个不同的概念需要你理解:

字符串文字,如@9​​87654321@、"""my string literal" 字符串变量

第一个是char[n] 类型的不可修改(修改它们是UB)数组,其中n 是实际字符数加上空字符 '\0' ,它表示字符串的结尾并且必须始终存在。您可以使用数组订阅运算符直接访问其各个元素,例如"abc"[1] 结果为 'b' 字符。

第二个是程序员声明的数组,可以保存 C 字符串。例如:

#define STR_LEN 60

char str[STR_LEN+1] = "abc";

不要将数组初始值设定项与"abc" 字符串字面量混淆,它们是相同的东西。实际上这样的初始化器(对于这个数组大小)相当于:

char str[STR_LEN+1] = 'a', 'b', 'c', '\0';

要处理字符串文字,您需要 char 指针,而不是 char 数组:

char *p_str = "abc" /* "abc" is string literal */

char 数组被声明后,你不能直接给它分配字符串字面量,例如:

str = "def"; /* wrong, str is array, not pointer (not l-value) */

将新字符串分配给数组(字符串变量)的唯一方法是修改其元素,例如:

str[0] = 'd';
str[1] = 'e';
str[2] = 'f';
str[3] = '\0'; /* very important */

您可以编写一个函数来代替分配单个字符,例如:

char *my_strcpy(char dst[], const char *src)

    while ((*dst++ = *src++)) /* copying idiom */
        ;  
    return dst;

示例调用:

my_strcpy(str, "def");
my_strcpy(str, p_str);

您可以使用strcpy(或者更安全的strncpy)来为您完成,而不是编写您自己的函数。故事结束。

【讨论】:

以上是关于为啥不能像这样复制char数组 charArray="some string";的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能使用 `section .data:` 和 `section .text:` 在 C 中创建一个长度超过 61 个字符的 char 数组? [复制]

为啥我不能像这样实例化一个对象? [复制]

为啥我不能在 Obj-C 中声明像“newVariable”这样的变量? [复制]

为啥 C 双星号不能用于创建二维数组?

模板类赋值运算符类

Java题库——chapter7 多维数组