ошибка C2440: '=': невозможно преобразовать из 'char [5]' в 'char [20]' - PullRequest
3 голосов
/ 31 августа 2010

Это связано с моей предыдущей публикацией

Когда я создал Struct:

struct buffer
{
    char ProjectName[20];
       char ProjectID[20];
};

Теперь, когда я пытаюсь присвоить ему значения:

buffer buf;
buf.ProjectID = "3174";
buf.ProjectName = "NDS";

Я получаю эту ошибку:

error C2440: '=' : cannot convert from 'char [5]' to 'char [20]'

и для решения этой проблемы я попытался уменьшить размер структуры, как показано ниже (не должен быть способ сделать это):

struct buffer
{

    char ProjectName[4];
    char ProjectID[5];
};

и получить error C2106: '=' : left operand must be l-value

Ответы [ 5 ]

7 голосов
/ 31 августа 2010

Вы должны скопировать строку в массив:

strcpy(buf.ProjectName, "3174");

Будьте осторожны с длиной строк, копируемых в массивы

4 голосов
/ 31 августа 2010

Вы не можете назначать подобные строки в C ++.Вам необходимо использовать такую ​​функцию, как strcpy, чтобы скопировать строку.Или еще лучше использовать класс std::string

3 голосов
/ 31 августа 2010

Давайте рассмотрим первый случай:

buffer buf; 
buf.ProjectID = "3174"; 
buf.ProjectName = "NDS"; 

$ 2.13.4 / 1 - «Обычный строковый литерал имеет тип« массив из n константных символов »и длительность статической памяти (3.7)»

Тип "3174" равен char const [5], а тип "NDS" равен char const [4].При попытке присвоить 'buf.ProjectID' компилятор должен по существу преобразовать из 'char const [5]' в 'char const [20]'.Это преобразование не разрешено правилами C ++.Фактически, при следующей попытке выдается более подходящее сообщение об ошибке.

$ 8.3.4 / 5 - '[Примечание: преобразования, влияющие на l-значения типа массива, описаны в 4.2.Объекты массивов типов не могут быть изменены , см. 3.10.] ".

Другими словами, это означает, что имя массива является неизменяемым lvalue (это то, что говорится во втором сообщении компилятора).

$ 5.17-"Есть несколько операторов присваивания, все из которых группируются справа налево.Все они требуют модифицируемое lvalue в качестве своего левого операнда, а тип выражения присваивания - тип его левого операнда. "

Итак, вот сводка:

Чтобы выражение присваивания работало, левая часть должна быть изменяемым выражением LValue, однако массив является неизменяемым выражением Lvalue. Следовательно, ему нельзя присвоить.

3 голосов
/ 31 августа 2010

Это нормально, вы действительно не можете назначать значения таблицам char таким образом (существует множество различных решений, например, sprintf или strcpy). Но это проблема С, а не С ++.

Поскольку вы пишете код на C ++, вы должны использовать std :: string для управления строками (и метод c_str (), если вам нужно, чтобы эти строки были преобразованы в таблицы символов).

1 голос
/ 31 августа 2010

Мне жаль говорить, что C ++ здесь немного не интуитивен. Вы можете сказать:

char name[10] = "abcd";

и, учитывая ваше определение выше:

buffer buf = { "NDS", "3174" };

Последнее основано на взаимно-однозначном соответствии между полями в структуре и значениями в списке, поэтому мне пришлось изменить порядок, использованный в ваших назначениях.

Но вы не можете сделать свое

buf.ProjectName = "abcde";

Что на самом деле запрашивает в C ++, так это то, что buf.ProjectName загружается с указателем на память, содержащую символьные данные «abcde». Вы не можете этого сделать, поскольку само ProjectName является еще одним буфером для символьных данных, а не для указателя на символьные данные.

Таким образом, если у вас есть область источника и назначения, содержащая строки, оканчивающиеся NUL (Google ASCIIZ, если необходимо), вам необходимо использовать функцию поддержки для копирования из одной в другую:

strcpy(buf.ProjectName, "name");

Если размер ProjectName слишком мал, ваша строка может перезаписать память, которую компилятор не зарезервировал для ProjectName, что может вызвать сбой или ошибочный вывод. Вы можете защититься от этого - если относительные размеры строк явно не в порядке - используйте strncpy(buf.ProjectName, "name", sizeof buf.ProjectName). К сожалению, это означает, что buf.ProjectName может не содержать ожидаемое значение в полном объеме, что делает его сомнительным.

C ++ улучшает этот способ обработки текстовых данных, которые наследуются от C, с помощью класса std :: string. Вы можете просто сделать это:

#include <string>
struct Buffer
{
    std::string project_name_;
    std::string project_id_;
};
Buffer b;
b.project_name_ = "abcde"; // works with string literals.
b.project_id_ = b.project_name_;  // can copy from std::string to std::string
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...