Return string in C | SoloLearn: Learn to code for FREE!

0

Return string in C

Could not find satisfying ans. My question is simple: how to return string from a function in C. I know that string in C is basically nothing but an array of characters - that means that i cannot directly return “string”. But what is the correct or safest/most common way of doing it? In my task I cannot use Heap, so malloc is not an option. I need something like this: char *get_string(char **argv) { } int main(int argc, char **argv) { char *str = get_string(argv[1]); }

10/29/2020 6:56:54 PM

Lone Wolf

24 Answers

New Answer

+4

About what can be returned: Local variables reside on the stack, inside the current function's stack frame. As soon as the function ends, the data may still be alive, but can be overwritten at any moment - in other words, should be considered gone. String literals - the things in quotation marks - reside in the read-only data segment of the executable. I.e. in the actual file. The file is mapped into memory and resides there, including all defined strings (an other data), until the process is terminated and the file is unmapped from memory. Data in read-only memory cannot be modified. Static variables reside in the data segment or bss segment of the file and are mapped into the process memory space just like the read-only data segment. Those, however, are writeable memory regions. Data can be modified and exists until the process is terminated and the file unmapped from memory. Changes to the data/bss segments are not written to file, however. So, that cannot be used for persistence. Heap allocated memory resides in memory pages mapped at runtime into the process' memory space upon demand. They are alive until the process ends. What you return from the function is a pointer somewhere into memory. Whether that points into the rodata segment, the data segment, the bss segment, or the heap, doesn't matter. Only thing to consider is that pointing into read-only memory has the returned string be a constant string. Returning a pointer into a stack frame that becomes invalid after the function ends is not a good idea. The stack in consecutive, it grows and shrinks with function stack frames. The next function will occupy all or parts of the previous function's stack frame, and its local data will overwrite whatever was left behind.

+4

i would use a different strategy, but I don't want to delve into that here since it is foreign to the thread.

+4

You're welcome. As long as this discussion helped you a bit further, I'm happy.

+3

Thanks for the mention, Davide. The situation here is somewhat different from the one Daniel was facing. In particular, here, we do not have to create a new string at all. argv[*] resides on the stack just above the main function (i.e. outside the scope of any local function), any string literal resides in the read-only data segment. That means, unless you manage to wreck the stack, both strings have the lifetime of the entire program. So, no need to duplicate anything. The following ought to work fine, ignoring the fact that a user might forget to provide a string with option "-d", which would no be handled properly (*): char *get_delim(int argc, char ** argv) { for (int i = 0; i < argc; i++){ if (!strcmp(argv[i], "-d") && (i+1 < argc)) return argv[i+1]; } return " "; } *) For POSIX compliant implementations of C, there is a'getopt' function that helps deal with command line options.

+3

Lone Wolf, "-d" option apparently requires additional data. Now, what happens if someone calls $ ./prog -d -c ... and forgets the argument for option -d? Then option -c would be read as argument of -d instead of throwing an error that -d requires an argument. That is what goes wrong.

+3

That line was taken from LoneWolf's code. Take the "echo" program for instance. It prints out what you put in. Now, you don't want to recompile "echo" every time you want to print something different, right? Therefore, programs offer configuration options as well as arguments via the command line. Those are handed to the main function in an array of strings, usually named "argv". The size of that array is passed into main as well, and is usually called "argc". The difficulty with options is that they are often optional and, if given, they can appear in any order and may even be contracted. For example, to spawn a network listener on port 4000 on linux, you write: $ nc -lvnp 4000 Which is the program "nc" with four options: $ nc -l -v -n -p 4000 -l : listen -v : be verbose -n : don't do domain name resolution -p N: listen on port N "nc -lvnp 4000" has argc == 3, argv = { "nc", "-lvnp", "4000" } But you can also write any of the following $ nc -p 4000 -l -vn $ nc -l -p 4000 -n -v $ nc -p 4000 -lvn or any other combination. argc is 5, 6, and 4 for the above invocations. So, you cannot rely on any specific order, nor that mandatory arguments, like the source port for the -p option, are not forgotten by the user. Therefore, a tool like "getopt" is usually used to parse command line options.

+2

I suggest you to read Coder Kitten's answers to this question about not just how to return the string, but what's the best way to do it: https://www.sololearn.com/Discuss/2555983/?ref=app

+2

Coder Kitten 🐈 infinite thanks for the crash course on command line stuff! So if you are not allowed to use getopt and you already know the options in advance you can create an array of string with all the combinations of options, like: combo={"nc" "-l" "-lv" "-lvn" ecc.. } And put a loop before "return argv[i+1];" to check if argv[i+1] matches one of the combos Or even better you can create an array of strings with only the simple options "-l", "-v", "-c"... and then make a function that generates all the possible combinations for you.

+1

Also thank all of you guys :), it is great that people are still willing to help nowadays..

+1

Coder Kitten I haven't fully understood this line if (!strcmp(argv[i]), "-d") && (i+1 < argc)) I guess because you are speaking in terms of command line or something else that I don't know. But can't you just add a condition that check wether whatever follows -d is -c? edit: if argc represent the length of argv, I get the meaning of the line. But is it necessary to pass the length? you can just create the local variable len=strlen(argv[0]) Anyway I understand that I am speaking about things that I don't know so if I am being wrong don't bother to explain me anything at all

0

argv[1] already returns string, you can print it with printf("%s", argv[1]); but only if you put arguments to your program

0

Yes I know, but it is little bit more complicated - that string which I want to store in variable “str” is not the argv[1]. It can be any argument passed when you run the program. And I do not want to have unnecessarily long for loop with error chcecking in main, I d like to do it in seperate function - hence get_delim

0

Meanwhile Ive found a way, could anyone please check if its correct? or without unexpected behavior?

0

I will add the code in a moment

0

https://code.sololearn.com/c0fFkCRm0uGx/?ref=app

0

Btw, the code wont work in Sololearn, but works fine

0

Coder Kitten Ok, so correct me if I am wrong: returning string literals is Ok, because they are different from local vars(are alive throughout the program lifetime), so until I try modifying them, it is okay to work with them-returning from a func...

0

Coder Kitten and could you please clearify why not providing “-d” argument would not be handled properly? I thought that the func would just return str literal “ “, which is exactly what I want for that case.. Could something go wrong? Also ‘getopt’ would be great, but I am not allowed to use it :(

0

Thanks a lot again. I get it that it is diffiucult for you to completely understand what I want to do - I hadnt provided you with enough context but in spite of this you did great. Davide that line of code which you did not understand means that if current argument is equal to “-d” and there is one more argument available next to it then do the task... If I had not included (i+1 < argc) where argc is total number of arguments passed I would get “segmentation fault” because I do not have access to that memory place... if you have an idea how to make it more readable or efficient, it is very much welcome. Coder Kitten I understand now how you meant it -> but in a scenario when user types “-d -c” it would be considered that -c is the delimeter, it is perfectly fine, even though he might have wanted to use -c as the next argument-it is considered as users fault and he needs to type it again, otherwise -c is the delimeter..

0

If you want I will give you more context so that you can understand it more(but I will include only the delimeter part for simplicity):