Сохранение char в массиве char – несовместимые типы при присвоении char char[]

У меня есть структура с элементом массива символов как таковая:

typedef struct {
    // ...
    char myCharArr[200];
} myStruct;

У меня есть динамический массив этих структур. Когда я пытаюсь сохранить символ в myCharArray, появляется сообщение об ошибке incompatible types in assignment of 'char' to 'char[200]'.

int num = 2;
myStruct* data = new myStruct[num];

// ...

data[i].myCharArr = 'a';  // error here

Но если я использую строку ниже, она работает нормально

*data[i].myCharArr = 'a';

Через некоторое время я возвращаюсь к C++, поэтому был бы очень признателен, если бы кто-нибудь объяснил разницу между ними. Насколько я понимаю и помню, я могу использовать strcpy и другие варианты для сохранения строки записи в массив символов, но в данном случае это один символ. Почему разыменование массива помогает сохранить символ в chararray? Кроме того, как сюда относится нулевой терминатор?

Несвязано: typedef здесь больше похоже на C, чем на C++ при использовании с определением классов.

user12002570 01.08.2024 12:16

Через некоторое время я возвращаюсь к C++. Я могу использовать strcpy. У меня есть динамический массив этих структур. Почему бы не использовать std::string? А динамический массив в C++ создается с помощью std::vector. Ваш код больше похож на C, чем на C++. Если вы только начинаете изучать C++, я рекомендую вам ознакомиться с лучшими практиками современного программирования на C++.

PaulMcKenzie 01.08.2024 12:16

Что здесь i. Нам нужен минимальный воспроизводимый пример

user12002570 01.08.2024 12:18
myCharArr — это массив. Вы не можете назначить его одному char. Использование operator* разыменовывает его, и в случае массива вы получаете ссылку на первый символ, который вы можете присвоить char.
wohlstad 01.08.2024 12:18
data[i].myCharArr дает вам элемент данных myCharArr, который имеет тип массива char[200], и вы пытаетесь присвоить ему char.
user12002570 01.08.2024 12:19

Ваш массив символов содержит 200 символов. Интересно, кто из этих 200, по вашему мнению, data[i].myCharArr = 'a' изменится? Размышление об этом должно ответить на ваш вопрос. *data[i].myCharArr = 'a'; точно такой же, как data[i].myCharArr[0] = 'a';, так что это ответ на ваш второй вопрос. *x и x[0]быть одним и тем же — одно из правил C++, именно так * и [] работают.

john 01.08.2024 12:20

Последний вопрос: нулевой терминатор вообще отсутствует в вашем коде. Но если вы хотите, чтобы ваш массив завершался нулем, вам нужно добавить код, который сделает это, это не делается за вас. Например, data[i].myCharArr[0] = 'a'; data[i].myCharArr[1] = '\0'; завершает ваш массив нулем.

john 01.08.2024 12:24

присвоение значения массиву просто невозможно. Вы можете только копировать данные в массив. например, перебирая символы или используя другие средства, такие как std::memcpy

Raildex 01.08.2024 12:27

Имейте в виду, что ваш пример кода типичен для реализации C, но вы предоставили только тег C++. В C++ это выглядело бы немного иначе (в зависимости от контекста, который вы не предоставили). Скорее всего, вам следует использовать std::string вместо char[200].

Marek R 01.08.2024 12:40

приложение, над которым я работаю, написано на C++, но оно использует драйвер C MongoDB из-за некоторых проблем с его настройкой для cpp - следовательно, также и некоторый код C. i можно считать индексом динамического массива (поскольку я перебираю массив позже в коде). Замена i на 0 подойдет для воспроизведения

Suhaib Ahmad 01.08.2024 12:51

Примечание: не делайте этого myStruct* data = new myStruct[num]; в C++, избегайте явного использования операторов new/delete и usw std::vector<myStruct>. Если вы возвращаетесь к C++, возможно, будет хорошей идеей прочитать Основные рекомендации по C++, это даст вам больше информации о том, что изменилось.

Pepijn Kramer 01.08.2024 15:07

@PepijnKramer спасибо за ваш комментарий, да, как было сказано в принятом ответе, планируется реорганизовать различные части приложения для использования векторов. умные указатели и т. д.

Suhaib Ahmad 01.08.2024 15:15
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
12
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если бы кто-нибудь мог объяснить разницу между ними.

data[i].myCharArr дает нам элемент данных myCharArr, который имеет тип массива char[200], и вы пытаетесь присвоить ему символьный литерал 'a', что невозможно. Обратите внимание, что массивы в стиле c также распадаются на указатели (здесь char*).


С другой стороны, когда вы применяете operator* к *data[i].myCharArr, это эквивалентно написанию:

*(data[i].myCharArr)    //same as data[i].myCharArr;

из-за приоритета оператора .

На этот раз мы по-прежнему получаем char[200] от data[i].myCharArr, но он превращается в указатель char. Затем operator* разыменовывает этот указатель и дает нам char, которому можно присвоить 'a'.


Обратите внимание, что в современном C++ вы можете использовать std::string, std::array, std::vector и т. д. Кроме того, вы можете напрямую назвать класс вместо использования typedef.

Спасибо! приоритет оператора и переход к указателю теперь делают это намного понятнее. В конечном итоге я проведу рефакторинг для использования векторов для массива структур, а также интеллектуальных указателей в других частях в рамках улучшений приложения, но есть определенные аспекты, которые должны быть на C из-за драйвера mongodb.

Suhaib Ahmad 01.08.2024 12:58

@SuhaibAhmad, понятно. Пожалуйста :)

user12002570 01.08.2024 12:58

@SuhaibAhmad C++ прекрасно поддерживает библиотеки C (или драйверы). Само по себе это не является причиной не использовать C++ в вашем коде. Например, если у вас есть строка C++ и вы вызываете функцию, которой нужна строка C, вы просто используете методы c_str или data для преобразования.

john 01.08.2024 13:03

Вы создаете память myStruct динамически, используя новый оператор. Таким образом, он возвращает местоположение этой структуры в памяти. Если вы хотите получить доступ к значению по адресу или ссылке на переменную, вам необходимо разыменовать это значение. В C++ по умолчанию оператор * используется для получения значения в заданной ячейке памяти.

Например, новый myStruct[num]; который возвращает адрес, пусть это будет 3000, и он будет сохранен в data[0]. Если вы поместите data[0], это означает, что вы имеете дело или назначаете только адрес или местоположение этой структуры, то есть 3000, но не значения. Следовательно, вы не можете назначить.

Если вы поместите *(data[0]), это означает, что вы указываете значения в позиции 3000. Таким образом, вы можете назначать или изменять значения.

Приятного кодирования!!

Другие вопросы по теме