Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Fastest method to return a C string

Tags:

c++

performance

c

I have a simple function that takes a char and return a string, in C it looks like;

char* get_string(char c) {
  switch(c) {
    case 'A': return "some string";
    Case 'B': return "some other string";
...

And it works fine, but then I wanted my code to work in C++, and the C++ compilers throws a gazillions "deprecated conversion from string constant to ‘char*’". I understand the warning, but I'm not 100% sure what is the best way to implement the function so it will work, fast, on both C and C++. This function is being called a lot, it's an important bottleneck, so it has to be fast. My best try is;

char* get_string(char c) {
  char* str = (char*)malloc(50);
  switch(c) {
    case 'A':
      sprintf(str, "some string");
      return str;
    Case 'B':
      sprintf(str, "some other string");
      return str;
...
like image 312
Paul Kern Avatar asked Jul 24 '10 03:07

Paul Kern


2 Answers

Return a const char* instead of char*. The const in this context means "this pointer points to a constant pointee" - in other words, the caller cannot modify the returned string. This allows the compiler to place the strings in some memory location so the get_string() function can just return addresses to those strings. If the caller needs to modify the returned string, they can allocate their own buffer and copy it (preferably via std::string).

const char* get_string(char c) { 
  switch(c) { 
    case 'A': return "some string"; 
    case 'B': return "some other string"; 
...
like image 59
In silico Avatar answered Oct 02 '22 07:10

In silico


If you're returning a constant string (which in this case you are), your return value should be const char*. If you need to return a mutable string, the three ways to do it are, in general:

Force the caller to allocate the string beforehand

int get_string (char c, char* outstr, size_t outstr_len) 
{
   // Write the output into outstr using strcpy or similar
   // and return an error code if outstr_len is smaller than
   // the space required to store the string
}

This is the most idiomatic in C, but requires the most work on the caller's part.

Allocate the string on the caller's behalf

char* get_string (char c) 
{ 
   char* str = malloc(/* however big */);
   // ...
   return str;
}

Note that this method is relatively slow, and you will need to document that it is the caller's responsibility to free the returned string, and that it should be freed with free (as opposed to delete[]). You could use new[] and delete[] instead of malloc and free here, but I assume the only reason that you would do this is to inter-operate with C code.

Allocate a static buffer

char* get_string (char c) 
{ 
   static char* str[/* however big */];
   // ...
   return str;
}

Here, you must document how large the returned string is guaranteed to be, and that the caller is not to free it. The major drawback here is that subsequent calls to get_string will clobber previously returned strings.

Ed: Hm, markdown does not seem to like intermixing code and lists

like image 31
Tyler McHenry Avatar answered Oct 02 '22 08:10

Tyler McHenry