Return string C from function

I am trying to return the C string from a function, but not working. Here is my code.

char myFunction() { return "My String"; } 

I basically call it this way:

 int main() { printf("%s",myFunction()); } 

I also tried other ways for myFunction , but they do not work. For example:

 char myFunction() { char array[] = "my string"; return array; } 

Note. I can not use pointers!

A small guide to this problem: There is a function that determines which month it is, for example; if it is 1, then it returns January, etc. etc.

So, when he is going to print, he does it. printf("Month: %s",calculateMonth(month)); . Now the problem is how to return this line from the calculateMonth function.

+87
c
Sep 30 '09 at 5:59
source share
13 answers

your function signature should be:

 const char * myFunction() { return "My String"; } 

Edit:

Background:

Years passed from this post, and they never thought that it would be voted, because it is so fundamental to C and C ++. However, a slightly more detailed discussion is needed.

In C (for example, C ++), a string is just an array of bytes ending in a zero byte, so the term "string-zero" is used to represent this particular flavor of the string. There are other types of strings, but in C (and C ++) this taste is essentially understood by the language itself. Other languages ​​(Java, Pascal, etc.) use different methodologies to understand "my line".

If you ever use the Windows API (which is in C ++), you will see fairly regular functional parameters, such as: "LPCSTR lpszName". The 'sz' part represents this concept of "string-zero": an array of bytes with a null (/ zero) terminator.

Clarification:

For this "intro" I use the word "bytes" and "characters" interchangeably, because it is easier to learn in this way. Keep in mind that there are other methods (wide characters and multi-byte character systems - mbcs) that are used to manage international characters. UTF-8 is an example of mbcs. For the intro, I calmly “missed” all this.

Memory:

This means that a string like "my string" actually uses 9 + 1 (= 10!) Bytes. It is important to know when you finally get around dynamically distributing strings. Thus, without this "terminating zero", you have no line. You have an array of characters (also called a buffer) hanging in memory.

Data Durability:

Using a function this way:

 const char * myFunction() { return "My String"; } int main() { const char* szSomeString = myFunction(); // fraught with problems printf("%s", szSomeString); } 

... usually drop you off with random unhandled exceptions / segments, etc., especially down the road.

In short, although my answer is correct - 9 times out of 10 you will end up with a program that crashes if you use it that way, especially if you think it is “good practice” to do it that way. In short: this is usually not the case.

For example, imagine some time in the future, now we need to somehow change the line. As a rule, the encoder will "take the easy way" and (try) to write this code:

 const char * myFunction(const char* name) { char szBuffer[255]; snprintf(szBuffer, sizeof(szBuffer), "Hi %s", name); return szBuffer; } 

Thus, your program will fail because the compiler (may / may not) freed the memory used by szBuffer by the time printf() called in main() . (Your compiler should also warn you of such problems in advance).

There are two ways to return strings that will not be barf so easily.

  • return buffers (static or dynamically allocated) that live for a while. In C ++, use “helper classes” (for example, std::string ) to handle data durability (which requires changing the return value of a function) or
  • pass a buffer to a function that is filled with information.

Note that you cannot use strings without using pointers in C. As I showed, they are synonyms. Even in C ++ with template classes, there are always buffers (i.e. pointers) that are used in the background.

So, to better answer (now a modified question). (there will certainly be various “other answers” ​​that can be provided).

Safe Answers:

for example 1. using statically allocated lines:

 const char* calculateMonth(int month) { static char* months[] = {"Jan", "Feb", "Mar" .... }; static char badFood[] = "Unknown"; if (month<1 || month>12) return badFood; // choose whatever is appropriate for bad input. Crashing is never appropriate however. else return months[month-1]; } int main() { printf("%s", calculateMonth(2)); // prints "Feb" } 

What “static” does here (many programmers do not like this type of “distribution”) is that the rows fall into the program data segment. That is, he constantly stands out.

If you switch to C ++, you will use similar strategies:

 class Foo { char _someData[12]; public: const char* someFunction() const { // the final 'const' is to let the compiler know that nothing is changed in the class when this function is called. return _someData; } } 

... but it might be easier to use helper classes like std::string if you are writing code for your own use (and not part of the library for sharing with others). A.

for example 2. using buffers defined by a specific user:

This is all the more "fool-tested" way of passing lines around. The returned data is not subject to manipulation by the caller. That is, for example, 1 can easily be abused by the caller and subject you to application errors. Thus, it is much safer (although it uses more lines of code):

 void calculateMonth(int month, char* pszMonth, int buffersize) { const char* months[] = {"Jan", "Feb", "Mar" .... }; // allocated dynamically during the function call. (Can be inefficient with a bad compiler) if (!pszMonth || buffersize<1) return; // bad input. Let junk deal with junk data. if (month<1 || month>12) { *pszMonth = '\0'; // return an 'empty' string // OR: strncpy(pszMonth, "Bad Month", buffersize-1); } else { strncpy(pszMonth, months[month-1], buffersize-1); } pszMonth[buffersize-1] = '\0'; // ensure a valid terminating zero! Many people forget this! } int main() { char month[16]; // 16 bytes allocated here on the stack. calculateMonth(3, month, sizeof(month)); printf("%s", month); // prints "Mar" } 

There are many reasons why the second method is better, especially if you are writing a library that others will use (you do not need to block a specific allocation / release scheme, third parties cannot break your code, you do not need to reference a specific memory management library), but , like all code, it depends on what you like best. For this reason, most people choose, for example, 1, until they are burned so many times that they no longer want to write it;)

Denial of responsibility:

I retired a few years ago and now my C is a little rusty. This demo code should fully compile with C (this is normal for any C ++ compiler, though).

+184
Sep 30 '09 at 6:03
source share

String C is defined as a pointer to an array of characters.

Unless you have pointers, by definition you cannot have strings.

+12
Sep 30 '09 at 6:06
source share

Check out this new feature:

 const char* myFunction() { static char array[] = "my string"; return array; } 

I defined the "array" as static, otherwise, when the end of the function, the variable (and the return pointer) goes out of scope. Since this memory is allocated on the stack, it will be corrupted. The disadvantage of this implementation is that the code is not repetitive, not thread safe.

Another alternative would be to use malloc to allocate a line on the heap, and then free at the right place in your code. This code will be reused and stream safe.

EDIT:

As noted in the comment, this is a very bad practice, since an attacker can then enter the code into your application (he needs to open the code with gdb, then make a breakpoint and change the value of the returned variable to overflow and the fun is just beginning).

If it is more recommended that the caller handles the memory allocation. See this new example:

 char* myFunction( char* output_str, size_t max_len ) { const char *str = "my string"; size_t l = strlen(str); if (l+1 > max_len) { return NULL; } strcpy(str, str, l); return input; } 

Please note that the only content that can be changed is the one that the user has. Another side effect is that this code is now thread safe, at least from a library point of view. The programmer calling this method must verify that the memory section is being used in streaming mode.

+8
Sep 30 '09 at 6:10
source share

Your problem is with the return type of the function - it should be:

 char *myFunction() 

... and then your original wording will work.

Note that you cannot use C strings without pointers, somewhere along the line.

Also: enable compiler warnings, it should have warned you about this return line converting char * to char without an explicit cast.

+7
30 Sep '09 at 6:02
source share

Based on your recently added background with the question, why not just return an integer from 1 to 12 for a month, and let the main () function use a switch or if-else statement to decide what to print? This, of course, is not the best way to go - char * will be - but in the context of such a class, I think that it is probably the most elegant.

+5
Sep 30 '09 at 6:25
source share

You can create an array in the caller, which is the main function, and pass the array to the caller, which is your myFunction (). This way myFunction can fill a string in an array. However, you need to declare myFunction () as

 char* myFunction(char * buf, int buf_len){ strncpy(buf, "my string", buf_len); return buf; } 

and in the main function myFunction should be called this way

 char array[51]; memset(array,0,51);/*all bytes are set to '\0'*/ printf("%s", myFunction(array,50));/*buf_len arguement is 50 not 51. This is to make sure the string in buf is always null-terminated(array[50] is always '\0')*/ 

However, the pointer is still in use.

+3
Apr 02 '14 at 10:23
source share

The type of the returned function is one char. You must return a pointer to the first element of the character array. If you cannot use pointers, then you are screwed. :(

+2
Sep 30 '09 at 6:01
source share

Or how about this:

 void print_month(int month) { switch (month) { case 0: printf("january"); break; case 1: printf("february"); break; ...etc... } } 

And call it the month that you calculate somewhere else.

Hello,

Sebastiaan

+2
Sep 30 '09 at 8:57
source share

A char is just one single byte character. It cannot store a character string and is not a pointer (which you apparently can't). Therefore, you cannot solve your problem without using pointers (for which char[] uses syntactic sugar).

+1
Sep 30 '09 at 6:02
source share

If you really can't use pointers, do the following:

 char get_string_char(int index) { static char array[] = "my string"; return array[index]; } int main() { for (int i = 0; i < 9; ++i) printf("%c", get_string_char(i)); printf("\n"); return 0; } 

The magic number 9 is horrible, this is not an example of good programming. But you understand. Note that pointers and arrays are the same thing (kinda), so this changes a bit.

Hope this helps!

+1
Sep 30 '09 at 6:17
source share

In the code, you are trying to return a String (In C , which is nothing more than a null terminated array of characters), but the return type of your function is char , which causes all the problems for you. Instead, you should write this:

 const char * myFunction ()
 {

     return "My String";

 }

And it is always useful to qualify your type with const when assigning literals in C to pointers, since literals in C do not change.

+1
May 09 '11 at 19:42
source share

Your function prototype claims your function will return a char. Thus, you cannot return a string to your function.

0
Sep 30 '09 at 6:03
source share
 char* myFunction() { return "My String"; } 

In C string literals, these are arrays with a static constant of a memory class, so returning a pointer to this array is safe. More details here: "lifetime" of a string literal in C

0
Jun 28 '19 at 15:12
source share



All Articles