0

I have the following stupid snippet:

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    const string classpath = "Hello Dolly!";
    const int len = classpath.length()+1;
    char str[len];
    strncpy(str, classpath.c_str(), len);
    cout << str << endl;
    return 0;
}

The aim ist to assign a c++ string to a c char array. The string is known at compile time, hence a constant. But the string may vary from one project to an other. I have no intention to count chars for the compiler. Hence the const len should be computed at compile time as shown. This works with cygwin and on linux. But the visualstudio compiler sees a problem and gives me the error C2131! How to work around? (Please consider I'm a Java programmer being troubled loosing time on such kind of problems!)

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
juerg
  • 381
  • 4
  • 18
  • 6
    `char str[len];` -- This is not valid C++, regardless of the compiler. C++ requires arrays to use constants to denote the number of items. Use `std::vector str(len)` instead. – PaulMcKenzie Apr 19 '17 at 17:40
  • 1
    Essentially this: http://stackoverflow.com/questions/43233894/tuple-stdget-not-working-for-variable-defined-constant/43234198#43234198 – NathanOliver Apr 19 '17 at 17:42
  • gcc and clang allow [VLAs as an extension](http://stackoverflow.com/q/21273829/1708801) ... VLAs are from C99 and are not standard C++ – Shafik Yaghmour Apr 19 '17 at 17:42
  • 1
    Since `classpath.length()` does not run at compile time, I would not expect `len` to be a compile time constant. – chux - Reinstate Monica Apr 19 '17 at 17:42
  • 1
    Could use `char str[] = "Hello Dolly!";` – chux - Reinstate Monica Apr 19 '17 at 17:43
  • @juerg -- *please read what I'm saying!* -- Please read what we're saying. An array in C++ cannot use a variable to denote the number of elements. I don't know how more simply to put it. – PaulMcKenzie Apr 19 '17 at 17:43
  • 1
    @PaulMcKenzie Well it can, it just need to be a compile time constant variable. – NathanOliver Apr 19 '17 at 17:45
  • @NathanOliver Hmmm "constant variable"? Do not find that in the C++ spec. Perhaps constant object? – chux - Reinstate Monica Apr 19 '17 at 17:45
  • *compile time constant variable* -- Sounds like an oxymoron, "constant variable" – PaulMcKenzie Apr 19 '17 at 17:45
  • I think the technical term is *core constant expression* – NathanOliver Apr 19 '17 at 17:48
  • please don't be fixed to much on the snippet. char str[] = "what ever"; can't be used. the string is comming from c++ part and c char array is in a library! How to have the compiler compute a constexpr? – juerg Apr 19 '17 at 17:48
  • @juerg MSVC does not support variable length arrays in C, and never has. – Weather Vane Apr 19 '17 at 17:52
  • [gcc gives you a warning here when the proper command line is used](http://rextester.com/WIUP19583) – PaulMcKenzie Apr 19 '17 at 17:52
  • @Weather Vane and how do you do it? count the caracters and put the number into the array definition? Even MSVC should offer a smarter solution! – juerg Apr 19 '17 at 17:56
  • @juerg No, it has nothing to do with MSVC. The C++ language specification does not allow variable length arrays. There is no requirement for Visual C++ or any other C++ compiler to "break the rules". – PaulMcKenzie Apr 19 '17 at 17:57
  • @Rakete 111 You should not edit questions if you don't understand the problem. The tags were correct. It's a problem of c++ and c and MSVC! – juerg Apr 19 '17 at 17:58
  • @PaulMcKenzie Not if you use c++11 or c++14 – juerg Apr 19 '17 at 17:59
  • @juerg No, Visual Studio has nothing to do with it. You should only use this tag if you have a specific question about it, not a coding issue. C++ doesn't have VLAs, those are only available via an extension. – Rakete1111 Apr 19 '17 at 18:00
  • @juerg VLA is not in C++ standard, neither in C++11 nor C++14 – Slava Apr 19 '17 at 18:00
  • @juerg Even in C++ `11 or 14, variable length arrays are not allowed. You just stumbled across an extension supported by a certain compiler, and even then, that compiler gives you a warning (or error) if you use the proper command-line arguments to compile your program. Consider yourself unlucky. – PaulMcKenzie Apr 19 '17 at 18:00
  • 1
    @Paul McKenzie Ok, but this is not the point, otherwise I would have used vector as already suggested. What I want is to define the array size at compile time and let the compiler compute the space required. Is this so difficulte with C++/c? – juerg Apr 19 '17 at 18:02
  • Then you're going about it all wrong by introducing `std::string` into this whole thing. A `char` array can always have its size known at compile time using `sizeof(array)` [See this](http://rextester.com/TUHPC27655) – PaulMcKenzie Apr 19 '17 at 18:11
  • I'm just showing a condensed example of a much bigger part. So we must accept, the c++ string being given, as well as the requirement to copy the beast to a c char array. For me this should be very simple. I conclude it's not, and this is very strange to me! Hence, once again, how do you do it? Count characters? – juerg Apr 19 '17 at 18:18
  • @juerg A `std::string` is a dynamic string class. Nothing about a `std::string` is known at compile time in terms of the number of characters it may hold later on. Given that, you have to use runtime solutions, and `std::vector`, or using `std::string` throughout your app, or using `new char[]` are those solutions. There are others, but those are the ones used the most. Like I said, you stumbled across something that really doesn't exist in C++ and Visual C++ slapped it down. – PaulMcKenzie Apr 19 '17 at 18:20
  • Aha, this is now a good answer. In Jave a String is not permutable and invariable. Hence the question is does c++ have a Java kind of String also? – juerg Apr 19 '17 at 18:23
  • Yes, it's called `std::string`. You used it, but thought it could be used as a compile-time entity when it really can't be used that way. – PaulMcKenzie Apr 19 '17 at 18:25
  • Btw why do you need to copy `std::string` content into array and not to use `std::string::c_str()` directly? – Slava Apr 19 '17 at 18:27
  • I must try if I can define it like this where required. If I understand correctly this will give me a c char array, from wich I can take the size before copy it to the destination char array, right? – juerg Apr 19 '17 at 18:31
  • What `std::string::c_str()` returns to you is already C string. Why do you need to copy it? – Slava Apr 19 '17 at 18:37
  • @juerg I think you should just use `std::string` throughout, and use `std::string::c_str()` for when you are interfacing to a function that requires a `const char *`. You may be making the mistake of thinking that if a function requires a char array, you **must** declare a char array and pass it to that function. That is not the case. – PaulMcKenzie Apr 19 '17 at 18:39
  • OK. I didn't get an answer as expected but at least the conlusion c/c++ can not offer me the solution expected. Thanks any way all of you for the discussion. I'll start look for a work around to get the goal. – juerg Apr 19 '17 at 18:44

1 Answers1

0

In C++ array sizes must be known at compile time.

You can dynamically allocate contiguous memory during run-time by using operator new:

char * my_array = new char[length];

Remember to use the delete[] to free up the memory after you are finished with it.

Also, C-style arrays need that terminating nul character so you will need to allocate one extra slot in the array.

To copy a std::string to a character array:

const std::string example = "example";
const std::string::size_type length = example.length();
char * p_array = new char [length + 1];
strcpy(p_array, example.c_str());
cout << p_array << endl;
delete[] p_array;
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • Sorry, this is not the point! I will not and can't use new! Please explain to this lazy Java programmer, used to let the compiler do the work, how you define a char array with the length defined by a c++ sting? Do you count the characters and put the number in? Or do you define simply much bigger than required? I can't believe this being the answer! – juerg Apr 19 '17 at 18:10
  • "Please explain to this lazy Java programmer, used to let the compiler do the work, how you define a char array with the length defined by a c++ sting?" You do not do it. That's it. – Slava Apr 19 '17 at 18:13
  • Do you have also a more helpful answer? – juerg Apr 19 '17 at 18:20
  • 1
    What answer do you want? Language does not support VLA, and that `const int` is not compile time constant, so this not going to work. You need to reserve big enough array or allocate memory dynamically. Or do not use `std::string` in between. – Slava Apr 19 '17 at 18:22