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?

1
  • 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. Commented Sep 7, 2018 at 5:45

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

9 Comments

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.
@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?
@SkepticalEmpiricist Thanks your answer did clarify my doubt. No need for further explaination.
@SkepticalEmpiricist: Your program isn't valid since C++11.
@SkepticalEmpiricist You spend on this almost 7 hours, researching. ;) and came up with a good answer. Worth an Up :)
|
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;

1 Comment

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.
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!

7 Comments

You could also define cb parameter to be of type std::string
Using const for the data members is not a great idea
@M.M. You make it sound like that's an innately bad thing.
Granted if you want to put this in a container I suppose you're better off with mutable but private members that cannot be modified via the provided API
Yeah okay fine ^_^
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.