Initializing char array from constant

  • A+
Category:Languages

I'm starting with this code:

void func1() {   char tmpfile[] = "/tmp/tmpXXXXXX";   mkstemp(tmpfile);  // Note: mkstemp modifies the char array, cannot be const   ... }  void func2() {   char tmpfile[] = "/tmp/tmpXXXXXX";   mkstemp(tmpfile);  // Note: mkstemp modifies the char array, cannot be const   ... } 

I'd like to refactor this to pull out the shared "/tmp/tmpXXXXXX" constant. Here is an attempt:

constexpr char kTmpfile[] = "/tmp/tmpXXXXXX";  void func1() {   char tmpfile[] = kTmpfile;   mkstemp(tmpfile);  // Note: mkstemp modifies the char array, cannot be const   ... }  void func2() {   char tmpfile[] = kTmpfile;   mkstemp(tmpfile);  // Note: mkstemp modifies the char array, cannot be const   ... } 

However, this doesn't compile. Changing tmpfile[] to tmpfile[sizeof(kTmpfile)] also doesn't work.

The below does work, but it uses a macro which is discouraged by my company's style guide (which is based on the Google Style Guide).

#define TMPFILE "/tmp/tmpXXXXXX"  void func1() {   char tmpfile[] = TMPFILE;   mkstemp(tmpfile);  // Note: mkstemp modifies the char array, cannot be const   ... }  void func2() {   char tmpfile[] = TMPFILE;   mkstemp(tmpfile);  // Note: mkstemp modifies the char array, cannot be const   ... } 

Is there any way to write this "nicely"? Without having to use a macro or hardcode the size? Or is the macro the best option for readability and maintainability?

 


Here are three approaches. Credit goes to @πάνταῥεῖ, @PSkocik, and @Asu for suggesting these, I just typed them up.

Approach 1a

constexpr auto kTmpfile = "/tmp/tmpXXXXXX";  void func1() {   std::string tmpfile = kTmpfile;   mkstemp(tmpfile.data());   ... } 

Advantages:

  • less code / more readable

Disadvantages:

  • C++17 only, because std::string::data returns a const char* in C++14 and earlier (of course, you can use a const_cast in C++14, but that's also bad)
  • may be slower, since char array may be allocated on the heap instead of stack

Approach 1b

constexpr auto kTmpfile = "/tmp/tmpXXXXXX";  void func1() {   std::string tmpfile = kTmpfile;   mkstemp(&tmpfile[0]);   ... } 

Advantages:

Disadvantages:

  • may be slower, since char array may be allocated on the heap instead of stack

Approach 2

constexpr char kTmpfile[] = "/tmp/tmpXXXXXX";  void func1() {   char tmpfile[sizeof(kTmpfile)];   memcpy(tmpfile, kTmpfile, sizeof(kTmpfile));   mkstemp(tmpfile);   ... } 

Advantages:

  • only uses stack, no heap
  • compatible with C++14 and earlier

Disadvantages:

  • more verbose / less readable

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: