0

My intention is to create a char[] from the length of a char* I've already created.

I asked myself why this is not valid:

void copyStringsV2() {
    const char* source = "this is my string.";
    const int length = strlen(source);

    const char* dest[length];
}

The compiler gives me this hint:

Severity    Code    Description Project File    Line    Suppression State
Warning C4101   'str_b': unreferenced local variable    CStrings     
xxx\cstrings.cpp    46  
Error   C2131   expression did not evaluate to a constant   CStrings     
xxx\cstrings.cpp    161 
Error (active)  E0028   expression must have a constant value   CStrings     
xxx\CStrings.cpp    161 

May you can help me out here?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 5
    Have a look at [Why aren't variable-length arrays part of the C++ standard](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) – Imanpal Singh Sep 10 '20 at 14:37
  • 2
    What is your actual goal? Because this code is misconceived. Whatever you are really trying to do, there's a better way to do it. – john Sep 10 '20 at 14:48
  • 1
    question suffers from [xy problem](http://xyproblem.info/), please focus question on actual problem not on your solution of this problem. – Marek R Sep 10 '20 at 14:50
  • 2
    The compiler's not smart enough to realize that `const char* source = "this is my string.";` won't change at runtime, so `const int length = strlen(source);` won't change at runtime and therefore `length` could be a compile-time constant usable as an array dimension. – user4581301 Sep 10 '20 at 15:12
  • @user4581301 thanks you man, i just had on my mind that strlen is sth becoming true on runtime :) – SirRollalot Sep 10 '20 at 19:51
  • @skrrrt thanks for sharing – SirRollalot Sep 10 '20 at 19:51

4 Answers4

3

You are trying to declare a variable-length array, which is not a standard feature in C++. A fixed-length array must have its length known at compile-time. That is what the compiler error is complaining about.

If you don't know the length until runtime, you will have to allocate the copied string dynamically instead, such as via new[]:

void copyStringsV2()
{
    const char* source = "this is my string.";
    const int length = strlen(source);
    char* dest = new char[length+1];
    strcpy(dest, source);
    ...
    delete[] dest;
}

Or std::vector, so you don't need to use new[]/delete[] directly:

#include <vector>

void copyStringsV2()
{
    const char* source = "this is my string.";
    const int length = strlen(source);
    std::vector<char> dest(length+1);
    strcpy(dest.data(), source);
    ...
}

But, in this case, it would be better to use std::string instead:

#include <string>

void copyStringsV2()
{
    const char* source = "this is my string.";
    std::string dest = source;
    ...
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • buuut... this means that "const int length = strlen(source);" is evaluated at runtime. correct me if im wrong please! – SirRollalot Sep 10 '20 at 20:14
  • 1
    Yes, `strlen()` is evaluated at runtime only. If you want a compile-time evaluation, you would have to use something more like this instead: `const char source[] = "this is my string."; const int length = std::size(source)-1;` Or the `char_traits::length()` solution that @eerorika showed you. – Remy Lebeau Sep 10 '20 at 20:21
2

For starters you should use the type size_t instead of the type int in this declaration

const int length = strlen(source);
      ^^^

This constant is a constant of the run-time. So you may not use it in the declaration

const char* dest[length];

because here is declared a variable length array and variable length arrays (VLA) is not a standard C++ feature.

Also it is unclear why the type of elements of the array is const char * instead const char.

And moreover a constant object shall be initialized.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • thank you for sharing, i dont wanna be to curious but why i should use size_t instead of int? is that something which helps me to survive the first days and why? :D – SirRollalot Sep 10 '20 at 20:02
  • @SirRollalot size_t is the return type of the function strlen. In general an object of the type int can be not large enough to accommodate all values of the type size_t. – Vlad from Moscow Sep 10 '20 at 20:04
2

My intention is to create a char[]

const char* dest[length];

That's not an array of char. That's an array of pointers to const char.

Also, if you want the array to be able to fit the original null termiated string, you must include the null terminator in the length of the array so that its size is length + 1.

I asked myself why this is not valid:

The compiler gives me this hint:

expression did not evaluate to a constant

May you can help me out here?

The size of an array must be a compile time constant. length is not a constant, therefore it cannot be used as length of an array.

Length of a string cannot be calculated at compile time through a pointer to element of the string. However, if you used a reference for example, and if you used a constexpr function to get the length, and used a constexpr (const works too) variable, then you could use it as the size of an array. There is such function in the C++ standard library:

auto& source = "this is my string.";
constexpr auto length = std::char_traits<char>::length(source);
char dest[length + 1];
eerorika
  • 232,697
  • 12
  • 197
  • 326
1

why this is not compilable

Because this is C++, and C++ provide a wide variety of tools already1. Your best bet will be std::string. Strings can be copied and passed around with no additional code to write.

#include <string>

int main()
{
    const std::string source = "this is my string.";
    const std::string dest = source;
    // do something with dest
}

1) So you don't need variable length arrays, which are not part of C++.

YSC
  • 38,212
  • 9
  • 96
  • 149
  • thanks for sharing, this will be the next chapter in my book. i just wanna learn als the basic stuff before i become lazy :D – SirRollalot Sep 10 '20 at 20:05
  • This is not laziness, this is c++. If you want useless complications try cobol. If you want useful complications, ho boy you'll be happy in the next chapters! – YSC Sep 10 '20 at 20:13
  • just wanna be capable of the stuff before i learn dealing with classes that makes my life a programmer easier. coming from java, some years of laziness already inside me :D – SirRollalot Sep 10 '20 at 20:27