Why can't I initialize the char array in the structure?

Viewed 572
typedef struct book {

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

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

} book;

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

3 Answers

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

cb1 is of type char*, but cb is a C-style array, a.k.a. formally as object of array type (this one specifically is a char[100]). Objects of array type cannot be modified (even though they are lvalues). If you only wish to shallow-copy and not strcpy() like you say, then you can define cb to be char* instead of char[100]:

typedef struct book {

   // ...
   char* cb;

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

} book;

But in most scenarios I wouldn't recommend doing so, as it would incur the precarious management of this raw pointer. This being tagged [C++], any reason not to use std::string?


Note: While you haven't tagged this [C++11] or above, further reason not to be using such raw pointers or C-style arrays like this is what would happen when you try using the above struct, probably like this:

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

A pretty standard compiler such as Clang will immediately let you know that1:

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

This implicit conversion from string literal (the type of which is const char[]) to char* was deprecated even in C++03, and now completely removed since C++11.

1 By default this will at least be a warning, and an error when built for example with -pedantic-errors.

You are asking that why you can't initialize the char[] in the struct ?

The answer to your question is because:

Arrays are ``second-class citizens'' in C; one upshot of this prejudice is that you cannot assign to them. An array isn't a modifiable lvalue in C & C++.

C & C++ both are different programming languages. Use of plain old C style arrays should be avoided in C++ because C++ language offers convenient and better alternatives of it.

Because this question has been tagged as C++ question, idiomatic solution would be to use std::string in C++.

So, it will be better if you do following:

#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;

Your post is tagged [C++], but isn't using modern idioms. Here's a version that allows for simple initialization. By using std::string, you avoid complicated init.

Note that you don't have to rename your parameters either.

Using 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;
}

Output

$main
Hello Woot!
Related