C ++: the fastest method for returning a C string

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

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 C ++ compilers generate gazillions "obsolete conversion from string constant to" char * ". I understand the warning, but I'm not 100% sure. what’s the best way to implement a function so that it works quickly in both C and C ++. This function is called a lot, this is an important bottleneck, so it should be fast. My best attempt:

 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; ... 
+5
c ++ performance c
Jul 24 '10 at 3:24
source share
6 answers

Return a const char* instead of char* . const in this context means that "this pointer points to a constant pointee" - in other words, the caller cannot modify the returned string. This allows the compiler to place lines in some memory location, so the get_string() function can simply return addresses to these lines. If the caller needs to change 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"; ... 
+18
Jul 24. '10 at 3:25
source share

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

Force the caller to pre-select the line

 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 element in C, but it requires most of the work to work.

Highlight Caller Name String

 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 the responsibility of the caller is to free the returned string and that it should be freed using free (as opposed to delete[] ). You can use new[] and delete[] instead of malloc and free here, but I assume that the only reason you do this is to interact with the C code.

Highlight static buffer

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

Here you must document how large the returned string is and that the caller does not release it. The main drawback here is that subsequent calls to get_string will discard previously returned rows.

Ed: Hm, markdown is not like mixed code and lists

+3
Jul 24 '10 at 3:31
source share

Make the original function return const char * instead of char * . The problem is const string literals. New compilers do not allow direct casting of them into a non-contact type.

+1
Jul 24 '10 at 3:28
source share

You can combine some of the solutions already proposed to make them even faster, but at some point you will achieve diminishing returns where additional efforts may not be practical.

I would return const char * using fixed strings and do it from a static array, assuming that you can guarantee that the original range is conditional (e.g. 'A' through 'C' ).

Using a static character array of constants means that the minimum cost is where a rewritable copy is not required. The cost of creating this array is likely to be at compile time, and not at run time. If the caller really wants a writable copy, they need to do something like:

 char *x = strdup ( get_string ('A')); 

(and, yes, I know that strdup not an ISO standard, but trivial to write ). Also, for raw speed, you can refuse to check for errors and make the assumption that callers will not transmit invalid values ​​in the contract part.

So something like:

 const char * get_string (char c) { static const char *arr[] = { "some string", // A "some other string" // B }; // any other value is undefined behaviour. return arr[c-'A']; } 

And this is important, do not think that this (or any other solution) will be the fastest based on what you think you know. Optimal Mantra - "Measure, Do Not Guess!" (and measure in a production environment).

+1
Jul 24 '10 at 4:30
source share

Use const char as others say. However, if this function is really a bottleneck, you should use a statically allocated array instead of a switch statement. You can improve the response time from O (n) to O (1) if you can just do:

 const char* MyStrings[100]; ... initialize MyStrings ... const char* get_string(char c) { return MyStrings[c-'A']; } 
0
Jul 24 '10 at 3:33
source share
 const char* get_string(char c) { static const char * case_a = "some string"; static const char * case_b = "some other string"; switch(c) { case 'A': return case_a; Case 'B': return case_b; ... 
-2
Jul 24 '10 at 3:37
source share



All Articles