Почему я не могу инициализировать массив символов в структуре?

typedef struct book {

   int a;
   int b;
   char cb[100];

   book(int a1, int b1, char* cb1) {
       a = a1;
       b = b1;
       cb = cb1;
   }

} book;

Почему я не могу инициализировать cb как cb1 и как это сделать без strcpy?

cb - это массив, а не указатель, и его нельзя присвоить. Это буквально память, которая уже выделена для вас внутри структуры, и вы получаете ключ ко всему. Это похоже на «Вот, я купил дом, он находится на Wayway Ave 39», и ваша жена говорит: «Отлично, вы можете просто переместить его через улицу на Wayway Ave 40?» Если вам нужен указатель, который вы можете назначить, вместо этого используйте char *cb.
Amadan 07.09.2018 07:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
262
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Why can't I initialise cb to cb1 and how to do it without strcpy?

cb1 относится к типу char*, но cb - это массив в стиле C, также известный как объект типа массива (в частности, char[100]). Объекты типа массив не может быть изменен (даже если они lvalue). Если вы хотите только мелкая копия, а не strcpy(), как вы говорите, тогда вы можете определить cb как char* вместо char[100]:

typedef struct book {

   // ...
   char* cb;

   book(int a1, int b1, char* cb1) {
       // ...
       cb = cb1;
   }

} book;

Но в большинстве случаев я бы не рекомендовал это делать., так как это повлечет за собой ненадежное управление этим необработанным указателем. Это помечено [C++], какая причина не использовать std::string?


Примечание. Хотя вы не пометили этот [C++ 11] или выше, дополнительная причина не использовать такие необработанные указатели или массивы в стиле C, подобные этому, - это то, что произойдет, когда вы попытаетесь использовать указанную выше структуру, возможно, так:

int main() {
    book b(4, 2, "Hello");
    return 0;
}

Достаточно стандартный компилятор, такой как Clang, сразу сообщит вам, что 1:

ISO C++11 does not allow conversion from string literal to 'char *'.

Это неявное преобразование из строковый литерал (тип которого - const char[]) в char* устарело даже в C++ 03, а теперь полностью удален с C++ 11.

1 По умолчанию это будет как минимум предупреждение и ошибка при сборке, например, с -pedantic-errors.

Вот этот тест, и мы можем использовать только iostream. Я новичок в cpp, поэтому вся эта работа с указателями меня действительно сбивает с толку.

Manish Madugula 07.09.2018 08:08

@ManishMadugula Хорошо, друг, без проблем. Значит, вам не разрешено использовать `std :: string '? Вы хотите, чтобы я добавил к ответу дополнительные пояснения относительно работы с этим указателем?

Geezer 07.09.2018 08:10

@SkepticalEmpiricist Спасибо, ваш ответ прояснил мои сомнения. Нет необходимости в дополнительных объяснениях.

Manish Madugula 07.09.2018 08:12

@SkepticalEmpiricist: Ваша программа недействительна с C++ 11.

Destructor 07.09.2018 08:12

@Destructor Я просто не смог найти пункт в спецификации, у вас есть его, чтобы я мог добавить к ответу?

Geezer 07.09.2018 08:13

@SkepticalEmpiricist: см. это и ответ это для получения дополнительной информации. Надеюсь, вы обновите свой ответ.

Destructor 07.09.2018 08:17

@Destructor Несмотря на то, что мой фрагмент был действителен, так как он не включал то, что я добавил по вашему запросу, я полностью согласен с вами, это важно отметить. Большое спасибо за продвижение вперед и дайте мне знать, если вы увидите что-нибудь еще, так что измените / добавьте.

Geezer 07.09.2018 08:32

@Destructor Также я думаю, что нашел соответствующий пункт в стандарте, я использовал его сейчас как ссылку в другом редактировании. Дайте мне знать, как у вас дела!

Geezer 07.09.2018 08:54

@SkepticalEmpiricist Вы тратите на это почти 7 часов, исследуя. ;) и придумал хороший ответ. Стоит поднять :)

JeJo 07.09.2018 15:36

Вы спрашиваете, почему вы не можете инициализировать char[] в struct?

Ответ на ваш вопрос:

Массивы - это `` граждане второго сорта '' в C; одним из следствий этого предубеждения является то, что вы не можете их приписать. Массив не является изменяемым lvalue в C и C++.

C и C++ - это разные языки программирования. В C++ следует избегать использования простых массивов в старом стиле C, потому что язык C++ предлагает удобные и лучшие альтернативы.

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

Итак, будет лучше, если вы сделаете следующее:

#include <string>

struct book {

   int a;
   int b;
   std::string cb;

   book(int a1, int b1, std::string cb1) {
       a = a1;
       b = b1;
       cb = cb1;
   }

} book;

Я бы не сказал, что массивы - это люди второго сорта. Типы массивов - это полноценные типы. Они настоящие, а не призраки. У них есть хранилище, срок службы и все остальное, чего вы ожидаете. Вы можете легко передавать указатели и ссылки на них, и (когда они завернуты в класс) также могут быть скопированы / перемещены. Лично я считаю правило распада имени, а также невозможность копирования через прямое присвоение отдельными странностями. В любом случае, это не имеет значения, потому что OP пытается инициализировать массив из указателя, который уже ошибочен.

Lightness Races in Orbit 07.09.2018 12:33

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

Обратите внимание, что вам также не нужно переименовывать свои параметры.

Использование std::string

#include <iostream>
#include <string>

class book {
public:
   int a;
   int b;
   std::string cb;

   book(int a, int b, const char* cb)
    : a(a),
      b(b),
      cb(cb)
    {
    }
};

int main()
{
    using namespace std;
    const book test(5, 17, "Woot!");
    cout << "Hello " << test.cb << endl; 

    return 0;
}

Выход

$main
Hello Woot!

Вы также можете определить параметр cb как тип std::string

Destructor 07.09.2018 08:07

Использование const для элементов данных - не лучшая идея

M.M 07.09.2018 09:30

@ M.M Почему это? Думаю наоборот. Используйте const по умолчанию, если вы не чувствуете, что вам нужно иметь возможность что-то изменить в какой-то момент (и, похоже, в этом нет необходимости).

Lightness Races in Orbit 07.09.2018 12:34

@LightnessRacesinOrbit делает класс не назначаемым

M.M 07.09.2018 12:36

@ M.M. Вы говорите так, будто это изначально плохо.

Lightness Races in Orbit 07.09.2018 12:37

Конечно, если вы хотите поместить это в контейнер, я полагаю, вам лучше использовать изменяемые, но частные члены, которые не могут быть изменены через предоставленный API.

Lightness Races in Orbit 07.09.2018 12:38

Да ладно хорошо ^ _ ^

Lightness Races in Orbit 07.09.2018 12:38

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