3
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?

Manish Madugula
  • 139
  • 1
  • 9
  • 2
    `cb` is an array, not a pointer, and cannot be assigned to. It is literally memory that's already allocated for you inside the struct, and you get the key to the lot. It's like "Here, I bought a house, it's on Wayway Ave 39" and your wife goes "great, can you just move it across the street to Wayway Ave 40?" If you want a pointer you can assign to, `char *cb` instead. – Amadan Sep 07 '18 at 05:45

3 Answers3

4

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.

Geezer
  • 5,600
  • 18
  • 31
  • There is this test and we can only use iostream. I am a beginner to cpp so all this deal with pointers is really confusing me. – Manish Madugula Sep 07 '18 at 06:08
  • @ManishMadugula OK friend no problem. So you're not allowed to use `std::string'? Do you want me to add additional explanation to the answer regarding working with this pointer? – Geezer Sep 07 '18 at 06:10
  • 1
    @SkepticalEmpiricist Thanks your answer did clarify my doubt. No need for further explaination. – Manish Madugula Sep 07 '18 at 06:12
  • @SkepticalEmpiricist: Your program isn't valid since C++11. – Destructor Sep 07 '18 at 06:12
  • @Destructor I just couldn't find the clause in the spec, do you have it so I could add to the answer? – Geezer Sep 07 '18 at 06:13
  • @SkepticalEmpiricist: see [this](http://coliru.stacked-crooked.com/a/9c8ad67ac8600bd9) and read [this](https://stackoverflow.com/questions/31816473/what-makes-this-usage-of-pointers-unpredictable/31817001#31817001) answer for more information. Hope you'll update your answer. – Destructor Sep 07 '18 at 06:17
  • @Destructor Even though my snippet was valid, as it didn't include what I've now added as per your request, I fully agree with you this is important to notice. Thanks a lot for pushing this forward and let me know if you see anything further so change/add. – Geezer Sep 07 '18 at 06:32
  • @Destructor Also I think I did find the relevant clause from the standard, I've used it now as a link in another edit. Let me know how this fares with you! – Geezer Sep 07 '18 at 06:54
  • 1
    @SkepticalEmpiricist You spend on this almost 7 hours, researching. ;) and came up with a good answer. Worth an Up :) – JeJo Sep 07 '18 at 13:36
1

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;
Destructor
  • 14,123
  • 11
  • 61
  • 126
  • 1
    I wouldn't say that arrays are second class citizens. Array types are fully fledged types. They're real things, not spectres. They have storage, lifetime, everything else you'd expect. You can pass around pointers and references to them just fine, and (when wrapped in a class) can be copied/moved around too. Personally I consider the name decay rule, along with inability to copy via direct assignment, to be isolated oddities. Anyway, it doesn't matter, because the OP is trying to initialise an array from a pointer which is already flawed. – Lightness Races in Orbit Sep 07 '18 at 10:33
1

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!
Will Bickford
  • 5,381
  • 2
  • 30
  • 45