C++ 错误:将'char*' 赋值给'char [2] 时的类型不兼容

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15914220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:53:48  来源:igfitidea点击:

C++ Error: Incompatible types in assignment of ‘char*’ to ‘char [2]

c++error-handlingchar

提问by vicR

I have a bit of a problem with my constructor. In my header file I declare:

我的构造函数有点问题。在我的头文件中,我声明:

char short_name_[2]; 
  • and other variables
  • 和其他变量

In my constructor:

在我的构造函数中:

Territory(std::string name, char short_name[2], Player* owner, char units);
void setShortName(char* short_name);
inline const char (&getShortName() const)[2] { return short_name_; }

In my cpp file:

在我的 cpp 文件中:

Territory::Territory(std::string name, char short_name[2], Player* owner, 
                     char units) : name_(name), short_name_(short_name), 
                    owner_(owner), units_(units)
{ }

My error:

我的错误:

Territory.cpp: In constructor ‘Territory::Territory(std::string, char*, Player*, char)': Territory.cpp:15:33: error: incompatible types in assignment of ‘char*' to ‘char [2]'

Territory.cpp:在构造函数 'Territory::Territory(std::string, char*, Player*, char)'中:Territory.cpp:15:33:错误:'char*' 到 'char [ 2]'

I already figured out that char[2] <=> char*but I'm not sure how to handle this about my constructor and get/setters.

我已经想通了,char[2] <=> char*但我不确定如何处理关于我的构造函数和 get/setter 的问题。

回答by David Brown

Raw arrays in C++ are kind of annoying and fraught with peril. This is why unless you have a very good reason to you should use std::vectoror std::array.

C++ 中的原始数组有点烦人,而且充满危险。这就是为什么除非您有充分的理由应该使用std::vectoror std::array

First off, as others have said, char[2]is not the same as char*, or at least not usually. char[2]is a size 2 array of charand char*is a pointer to a char. They often get confused because arrays will decay to a pointer to the first element whenever they need to. So this works:

首先,正如其他人所说,char[2]与 不同char*,或者至少通常不同。char[2]是一个大小为 2 的数组,char并且char*是一个指向 a 的指针char。他们经常感到困惑,因为数组会在需要时衰减为指向第一个元素的指针。所以这有效:

char foo[2];
char* bar = foo;

But the reverse does not:

但反过来不会:

const char* bar = "hello";
const char foo[6] = bar; // ERROR

Adding to the confusion, when declaring function parameters, char[]is equivalent to char*. So in your constructor the parameter char short_name[2]is really char* short_name.

更令人困惑的是,在声明函数参数时,char[]等效于char*. 所以在你的构造函数中,参数char short_name[2]真的是char* short_name.

Another quirk of arrays is that they cannot be copied like other types (this is one explanation for why arrays in function parameters are treated as pointers). So for example I can notdo something like this:

数组的另一个怪癖是它们不能像其他类型一样被复制(这是为什么函数参数中的数组被视为指针的一种解释)。所以例如我不能做这样的事情:

char foo[2] = {'a', 'b'};
char bar[2] = foo;

Instead I have to iterate over the elements of fooand copy them into bar, or use some function which does that for me such as std::copy:

相反,我必须遍历 的元素foo并将它们复制到 中bar,或者使用一些为我执行此操作的函数,例如std::copy

char foo[2] = {'a', 'b'};
char bar[2];
// std::begin and std::end are only available in C++11
std::copy(std::begin(foo), std::end(foo), std::begin(bar));

So in your constructor you have to manually copy the elements of short_nameinto short_name_:

因此,在您的构造函数中,您必须手动将元素复制short_nameshort_name_

Territory::Territory(std::string name, char* short_name, Player* owner, 
                     char units) : name_(name), owner_(owner), units_(units)
{ 
    // Note that std::begin and std::end can *not* be used on pointers.
    std::copy(short_name, short_name + 2, std::begin(short_name));
}

As you can see this is all very annoying, so unless you have a very good reason you just should use std::vectorinstead of raw arrays (or in this case probably std::string).

正如您所看到的,这一切都非常烦人,因此除非您有充分的理由,否则您应该使用std::vector而不是原始数组(或者在这种情况下可能是std::string)。

回答by Oswald

When a function wants an array as argument, it gets a pointer to the first element of an array instead. This pointer cannot be used to initialize an array, because it's a pointer, not an array.

当一个函数想要一个数组作为参数时,它会得到一个指向数组第一个元素的指针。这个指针不能用于初始化数组,因为它是一个指针,而不是一个数组。

You can write functions that accept referencesto arrays as arguments:

您可以编写接受对数组的引用作为参数的函数:

void i_dont_accept_pointers(const char (array&)[2]) {}

The problem here is, that this array reference cannot be used to initialize another array.

这里的问题是,这个数组引用不能用于初始化另一个数组。

class Foo {
  char vars[2];
  Foo(const char (args&)[2])
    : vars(args)  // This will not work
  {}
};

C++ 11 introduced std::arrayto eliminiate this and other problems of arrays. In older versions, you will have to iterate through the array elements and copy them individually or use std::copy.

引入 C++ 11std::array以消除数组的这个问题和其他问题。在旧版本中,您必须遍历数组元素并单独复制它们或使用std::copy.

回答by user12242622

C++ as C holds most of the rules of C.

C++ 作为 C 拥有 C 的大部分规则。

In case of C, always use char* to pass array because that how C looks at it. Even sizeof (short_name_)will be 8 or 4 when passed to function. Now, you have a space of 2 bytes in variable short_name_

在 C 的情况下,总是使用 char* 来传递数组,因为 C 是如何看待它的。sizeof (short_name_)传递给函数时甚至会是 8 或 4。现在,您在变量中有 2 个字节的空间short_name_

Constructor allocated memory for two bytes in short_name_and you need to copy the bytes into that or use a char * pointer and assume it's size if 2.

构造函数为两个字节分配了内存short_name_,您需要将字节复制到其中或使用 char * 指针并假设它的大小为 2。

Chapter 9 from Expert C Programming: Deep C Secretsis good read to understand it.

来自Expert C Programming: Deep C Secrets 的第 9 章非常适合阅读以了解它。

For simplicity this could be C style code.

为简单起见,这可能是 C 风格的代码。

#include <stdio.h>
#include <iostream>
using namespace std;
class Territory {
    private:
        string s;
        char c[2];
    public:
    Territory(std::string a, char b[2] /*visualize as char *b*/) {
        s  = a;
        c[0] = b[0]; //or use strcpy
        c[1] = b[1];
    }
    void PrintMe() {
        printf ("As string %s as char %c or %s\n",this->s.c_str(), c[0],c);
    }
};


main () {
    Territory a("hello", "h");
    a.PrintMe();
}