Just trying to make a simple toString function but I'm having difficulty figuring out how I can create an sprintf style string without having to create a temporary variable.
i.e. It would be wonderful if the following worked
#myfile.c
bool status;
int state;
...
const char* myfileToString(void) {
return sprintf("myfile::status=%s;state=%d;", \
status ? "true" : "false", \
state);
}
this won't work since sprintf needs you to first create the string then pass it to the function.
i.e. I believe the following works
#myfile.c
bool status;
int state;
...
const char* myfileToString(void) {
char ret[40];
sprintf(ret, \
"myfile::status=%s;state=%d;", \
status ? "true" : "false", \
state);
return ret;
}
is there another function that I can use instead of sprintf or can I do something weird with sprintf like passing it some pointer to return directly sprintf(*return, "...", ...);
Okay...
Part 1:
Unless you're writing a macro, you don't need the backslash at the end of unfinished lines.
sprintf() requires a mutable buffer as it's first argument. You're not passing one, so you'll get all sorts of bad behavior here.
Part 2:
You're returning a pointer to a stack allocated object. That's going to cause undefined behavior.
What you should do:
Allocate the memory outside of this function. So:
void myfileToString(const char *str, size_t len) {
snprintf(str, len, "myfile::status=%s;state=%d;",
status ? "true" : "false",
state);
str[len - 1] = '\0';
}
You would call this by doing:
char box[40];
myfileToString(box, sizeof(box) /* 40 */);
Making this more reliable:
The family of sprintf() functions returns the number of characters written to a buffer. You could use this to send back an error (say a true or false return value) if the number of characters that was written was greater than the size of the buffer.
Finally, you could use the heap:
It's not the greatest practice, because it can mess with what people expect. But you could allocate memory on the heap for this data. You would need to remember to call free() on it in the future.
const char *myFileToString() {
char *str = malloc(40);
snprintf(str, 40, "myfile::status=%s;state=%d;",
status ? "true" : "false",
state);
str[40 - 1] = '\0';
}
In the first version you return what sprintf returns, which won't work as it doesn't actually return a string (please read the linked reference). In the second version of the function you return a pointer to a local variable, this leads to undefined behavior as the local variable goes out of scope when the function returns and the pointer no longer points to valid memory.
There are two primary solutions:
Allocate the string dynamically, e.g. using malloc, and return that pointer. Major drawback is that you must free the pointer you return.
Pass a character array as argument to the function, and use that as destination for the string.
Also, you should rather use snprintf than plain sprintf, because then you can control how much is written to the destination string, so you don't get a buffer overflow. On Windows using the Visual C++ compiler it's called _snprintf.
You don't want to use a local variable to build your sting in. Once you return, the variable will be lost and your return value will be undefined. Instead you can either allocate memory in your routine with malloc(), or you can pass a pointer to preallocated memory into your routine.
In either case you ought to use snprintf() instead of sprintf() to make sure you don't overflow your buffer.
You can't return a char[] in a function because it is allocated statically (on your stack) and destroyed at the end of your function. For you toString function, you have to use malloc in order to return a char* allocated dynamically (in your heap)
Your first method is totally wrong! You should not use like that!
Instead of sprintf you can use snprintf
snprintf(ret,sizeof(ret),"myfile::status=%s;state=%d;",status ? "true" : "false",state);
I use this (very nasty) trick:
struct strang
{
char s[100] ; /* this is arbitrary, but has to be enough ! */
} ;
and, by way of an example, to convert a struct sockaddr to a suitable string:
struct strang
sockaddr2strang(struct sockaddr* sa)
{
struct strang str ;
struct sockaddr_in* sin ;
....
switch (sa->sa_family)
{
AF_INET:
sin = (struct sock_addr_in*)sa ;
inet_ntop(AF_INET, &sin->sin_addr, str.s, sizeof(str)) ;
break ;
....
} ;
return str ;
} ;
The cunning part is that you can use the result in an expression or as the argument for another function, for example:
printf("....%s..%s..", ...., sockaddr2strang(&sa_local).s,
...., sockaddr2strang(&sa_peer).s) ;
Note that this is entirely pthread-safe, and does not require the caller to set up and pass in any auxiliary buffer(s) -- in particular (as shown here) if more than one string is required at the same time, the caller doesn't have to manage two (or more) buffers etc.
Obviously, this will not work for return strings of arbitrary size.
Related
When passing values to my functions, I often consider either returning an allocated buffer from my function, rather than letting the function take a buffer as an argument. I was trying to figure out if there was any significant benefit to passing a buffer to my function (eg:
void f(char **buff) {
/* operations */
strcpy(*buff, value);
}
Versus
char *f() {
char *buff = malloc(BUF_SIZE);
/* operations */
return buff;
}
These are obviously not super advanced examples, but I think the point stands. But yeah, are there any benefits to letting the user pass an allocated buffer, or is it better to return an allocated buffer?
Are there any benefits to using one over the other, or is it just useless?
This is a specific case of the more general question of whether a function should return data to its caller via its return value or via an out parameter. Both approaches work fine, and the pros and cons are mostly stylistic, not technical.
The main technical consideration is that each function has only one return value, but can have any number of out parameters. That can be worked around, but doing so might not be acceptable. For example, if you want to reserve your functions' return values for use as status codes such as many standard library functions produce, then that limits your options for sending back other data.
Some of the stylistic considerations are
using the return value is more aligned with the idiom of a mathematical function;
many people have trouble understanding pointers; and in particular,
non-local modifications effected through pointers sometimes confuse people. On the other hand,
the return value of a function can be used directly in an expression.
With respect to modifications to the question since this answer was initially posted, if the question is about whether to dynamically allocate and populate a new object vs populating an object presented by the caller, then there are these additional considerations:
allocating the object inside the function frees the caller from allocating it themselves, which is a convenience. On the other hand,
allocating the object inside the function prevents the caller from allocating it themselves (maybe automatically or statically), and does not provide for re-initializing an existing object. Also,
returning a pointer to an allocated object can obscure the fact that the caller has an obligation to free it.
Of course, you can have it both ways:
void init_thing(thing *t, char *name) {
t->name = name;
}
thing *create_thing(char *name) {
thing *t = new malloc(sizeof(*t));
if (t) {
init_thing(t);
}
return t;
}
Both options work.
But in general, returning information through the parameters (the second option) is preferable because we usually reserve the return of the function to report an error. And we can return several information trough multiple parameters. Hence, it is easier for the caller to check if the function was OK or not by checking first the returned value. Most of the services from the C library or the Linux system calls work like this.
Concerning your examples, both options work because you are referencing a constant string which is globally allocated at program's loading time. So, in both solutions, you return the address of this string.
But if you do something like the following:
char *func(void) {
char buff[] = "example";
return buff;
}
You actually copy the content of the constant string "example" into the stack area of the function pointed by buff. In the caller the returned address is no longer valid as it refers to a stack location which can be reused by any other function called by the caller.
Let's compile a program using this function:
#include <stdio.h>
char *func(void) {
char buff[] = "example";
return buff;
}
int main(void) {
char *p = func();
printf("%s\n", p);
return 0;
}
If the compilation options of the compiler are smart enough, we get a first red flag with a warning like this:
$ gcc -g bad.c -o bad
bad.c: In function 'func':
bad.c:5:11: warning: function returns address of local variable [-Wreturn-local-addr]
5 | return buff;
| ^~~~
The compiler points out the fact that func() is returning the address of a local space in its stack which is no longer valid when the function returns. This is the compiler option -Wreturn-local-addr which triggers this warning. Let's deactivate this option to remove the warning:
$ gcc -g bad.c -o bad -Wno-return-local-addr
So, now we have a program compiled with 0 warning but this is misleading as the execution fails or may trigger some unpredictible behaviors:
$ ./bad
Segmentation fault (core dumped)
You can't return the address of local memory.
Your first example works because the memory in "example" will not be deallocated. But if you allocated local (aka automatic) memory it automtically be deallocated when the function returns; the returned pointer will be invalid.
char *func() {
char buff[10];
// Copy into local memory
strcpy(buff, "example");
// buff will be deallocated after returning.
// warning: function returns address of local variable
return buff;
}
You either return dynamic memory, using malloc, which the caller must then free.
char *func() {
char *buf = malloc(10);
strcpy(buff, "example");
return buff;
}
int main() {
char *buf = func();
puts(buf);
free(buf);
}
Or you let the caller allocate the memory and pass it in.
void *func(char **buff) {
// Copy a string into local memory
strcpy(buff, "example");
// buff will be deallocated after returning.
// warning: function returns address of local variable
return buff;
}
int main() {
char buf[10];
func(&buf);
puts(buf);
}
The upside is the caller has full control of the memory. They can reused existing memory, and they can use local memory.
The downside is the caller must allocate the correct amount of memory. This might lead to allocating too much memory, and also too little.
An additional downside is the function has no control over the memory which has been passed in. It cannot grow nor shrink nor free the memory.
You can only return one thing from a function.
For example, if you want to convert a string to an integer you could return the integer like atoi does. int atoi( const char *str ).
int num = atoi("42");
But then what happens when the conversion fails? atoi returns 0, but how do you tell the difference between atoi("0") and atoi("purple")?
You can instead pass in an int * for the converted value. int my_atoi( const char *str, int *ret ).
int num;
int err = my_atoi("42", &num);
if(err) {
exit(1);
}
else {
printf("%d\n");
}
How should I change the variable BinaryNumber, so the function will not give me a warning message.
I understand that I can't return a address of a local variable cause of the memory. Should I use malloc or what do you think how should I change the variable BinaryNumber so I can return it?
char *Functoin_chang_string_ToBinary(char *Line) {
char *space = " ", *point = ",";
char BinaryNumber[Array_Size] = { "000000000000000" };
char *word = strtok(Line,"\"");
int num = 0, flag = 2, j = 11;
for (int i = 0; i < strlen(Line) - 1; i++) {
if (word[i] == '"') {
flag--;
i++;
}
num = word[i];
j = 14;
while (num != 0) {
BinaryNumber[j--] += (num % 2);
num /= 2;
}
printf("%s\n", BinaryNumber);
Fill_Struct_Binary_Machine_Code("", BinaryNumber);
strcpy(BinaryNumber, "000000000000000");
}
printf("%s\n", BinaryNumber);
Fill_Struct_Binary_Machine_Code("", BinaryNumber);
return BinaryNumber;
}
Although you can use malloc() to allocate a buffer for the BinaryNumber string (which will, of course, need to be released by the caller using free()), a much simpler method would be to use the strdup() function.
This will allocate the exact amount of memory required to duplicate the string given as its argument (including the nul terminator) and copy the actual string data in one call.
Thus, you could just change your function's return statement to this:
return strdup(BinaryNumber);
Of course, the caller will still need to call free() on the returned data when it's done with it (strdup allocates the memory in a manner compatible with the malloc function).
Yes, you can return a pointer to memory allocated by malloc.
Alternatively, you could change the function prototype of Functoin_chang_string_ToBinary to the following:
void Functoin_chang_string_ToBinary(char *Line, char *BinaryNumber );
That way, the calling function can allocate the memory as a local array and pass a pointer to that array to the function Functoin_chang_string_ToBinary, for example like this:
BinaryNumber[Array_Size];
Functoin_chang_string_ToBinary( Line, BinaryNumber );
However, when passing pointers to memory buffers like this, it is also important to make sure that the called function does not write past the boundary of the buffer. For this reason, it would be better if the called function knew the size of the buffer it is being passed. Therefore, you may want to also pass the size of the buffer to the function, by changing the function prototype to the following:
void Functoin_chang_string_ToBinary(char *Line, char *BinaryNumber, int BinaryNumberSize )
The code of the calling function would then be changed to the following:
BinaryNumber[Array_Size];
Functoin_chang_string_ToBinary( Line, BinaryNumber, ArraySize );
That way, the called function can determine how large the memory buffer is, by accessing its third parameter.
Change your function signature to accept a target to save it to:
char *Function_chang_string_ToBinary_r(char *Line, char *out, size_t out_size )
Whenever you do this it is far safer to provide a maximum output size as not to overrun the target. You would also use size sensitive copies for copying to the target limiting copies to the smaller of the target area our your internal working area.
Look at the strtok() vs strtok_r() function for a model for a function that switched to this model to be thread safe.
Yes, malloc() would work but I tend to consider malloc() calls within a function a bad idea, expecialy for short strings. [1] it leaves callers open to memory leaks if they forget to free the memory you allocated and [2] if the function is called frequently malloc() can have a high overhead. Passing in a NULL pointer could make the function call malloc() anyway to return the new address. This way any memory leak or performance bugs would then be on the caller.
I need to create a DLL file that can be used for MS Access and other applications that will return a string when fed parameters. I am fairly familiar with MS Access but an absolute novice at C.
Following is the code I am experimenting with. I want to be able to issue a call like getstring(32.1, 123.2, "here", 25) and have it return a string of up to 60 characters in length. The actual code works fine and buf contains the string I want when it's finished running but I am having trouble handing it back to the calling function.
UPDATE:
Ok, I've worked out how to create a DLL and run a function from VBA but I am still struggling to understand how to return strings. I think if I can get this to work, I can work out my whole project. By running the following code I can get VBA to return the square of the input number e.g. feed it a parameter of 10 and I get an answer of 100
double _stdcall square(double *x)
{
return *x * *x;
}
However when I run the following code in Excel and feed it a parameter of "test" all I get back is a square box character.
char _stdcall Boxx(char *x)
{
return *x;
}
In this case all I want it to return is what I entered. If I can get it to return that I hope to be able to replace that with the actual result. Any suggestions?
char * Getstring(double lat, double lon, char *name, double zoom)
{
char buf[60] = { '\0' }; // Set the max length of the final link string
int ret = GenShortDroidMapUrl(lat, lon, zoom, name, buf, sizeof(buf) - 1);
return buf;
}
In the posted code, buf[] is an automatic variable whose lifetime ends after the Getstring() function has returned. Since buf[] will no longer exist when control of the program has returned to the caller, a pointer to this variable will be invalid after Getstring() has returned.
One solution is to pass an additional argument into the Getstring() function to accept the string, along with a size argument. Since buf will decay to a pointer in the function call, the sizeof operator can't be used in Getstring() to find the size of the array, but buf_sz holds this value:
char * Getstring(char *buf, size_t buf_sz, double lat, double lon, char *name, double zoom)
{
// buf[] has been zero-initialized in the caller
int ret = GenShortDroidMapUrl(lat, lon, zoom, name, buf, buf_sz - 1);
return buf;
}
Another option that does not require changing the function signature is to dynamically allocate storage for the returned string. Again, buf is a pointer to char in Getstring(), so the sizeof expression in GenShortDroidMapUrl() will need to be replaced; this time the constant BUF_SZ has been used here. Note that the malloced memory will need to be freed by the caller later.
#include <string.h>
#define BUF_SZ 60
/* ... */
char * Getstring(double lat, double lon, char *name, double zoom)
{
char *buf = malloc(sizeof *buf * BUF_SZ);
memset(buf, '\0', BUF_SZ);
/* Or use calloc() and avoid the call to memset() */
// char *buf = calloc(BUF_SZ, sizeof *buf);
int ret = GenShortDroidMapUrl(lat, lon, zoom, name, buf, BUF_SZ - 1);
return buf;
}
If Getstring() is part of a library, you need to ensure that the deallocator function matches the allocation functions. That is, there may be problems if the version of malloc() or calloc() that Getstring() is linked against differs from the version of free() that the calling code is linked against. One solution is to provide a deallocation function with the library. This could be as simple as wrapping free() in another function to be used by the caller to ensure that a matching deallocator is used. Here, the function DLL_Free() is part of the DLL, and malloc(), calloc(), and free() would all be linked against the same library when the DLL is created. The caller that uses Getstring() would use DLL_Free() to deallocate. From the caller, free() may not work as expected to deallocate the memory allocated by Getstring(), but DLL_Free() would since this deallocator uses the version of free() that matches the allocators used in the DLL.
/* Deallocation function included in DLL that matches allocation
* functions used in library
*/
void DLL_Free(void *ptr)
{
free(ptr);
}
There are many ways to return a string, but respect the lifetime of buffers:
Can a local variable's memory be accessed outside its scope?
One is to let the caller supply the buffer. Return how much space would have been needed, and a simple comparison will tell you whether it was enough.
Another is to use a static, optionally thread-local, buffer. Beware the restrictions on concurrency and reentrancy.
And finally, you can allocate it dynamically. Remember that it has to be freed with the same system, which on windows often means you have to manually export the way to free it from your DLL. Better not to reinvent the wheel, look at BSTRs for example.
You could either declare buf static and let the function return const char *. But that would not be reentrant. So another solution is to return strdup(buf), which will return a copy that the caller needs to free after use (otherwise you will have a memory leak).
I'm working on a program in C and one of my key functions is defined as follows:
void changeIndex(char* current_index)
{
char temp_index[41]; // note: same size as current_index
// do stuff with temp_index (inserting characters and such)
current_index = temp_index;
}
However, this function has no effect on current_index. I thought I found a fix and tried changing the last line to
strcpy(current_index, temp_index)
but this gave me yet another error. Can anyone spot what I'm doing wrong here? I basically just want to set the contents of current_index equal to that of temp_index at each call of changeIndex.
If more information is needed, please let me know.
strcpy should work if current_index points to allocated memory of sufficient size. Consider the following example, where changeIndex require additional parameter - size of distination string:
void changeIndex(char* current_index, int max_length)
{
// check the destination memory
if(current_index == NULL)
{
return; // do nothing
}
char temp_index[41];
// do stuff with temp_index (inserting characters and such)
// copy to external memory, that should be allocated
strncpy(current_index, temp_index, max_length-1);
current_index[max_length-1] = '\0';
}
Note: strncpy is better for the case when temp_index is longer then current_index.
Examples of usage:
// example with automatic memory
char str[20];
changeIndex(str, 20);
// example with dinamic memory
char * ptr = (char *) malloc(50);
changeIndex(ptr, 50);
Obviously defining a local char array on the stack and returning a pointer to it is wrong. You should never do that as the memory is not defined after the function ends.
In addition to the previous answers: The strncpy char pointer (which seems unsafe for my opinion), and the malloc which is safer but you need to remember to free it outside of the function (and its inconsistent with the hierarchy of the program) you can do the following:
char* changeIndex()
{
static char temp_index[41]; // note: same size as current_index
// do stuff with temp_index (inserting characters and such)
return temp_index;
}
As the char array is static it will not be undefined at the end of the function and you do not need to remember to free the pointer at the end of the use.
Caveat: If you are using multiple thread you cannot use this option as the static memory could be changed by different threads entering the function at the same time
Your array temp_index is local for function, then *current_index don't take what u want.
U can use also function strdup . Function return begin memory location of copied string , or NULL if error occurred, lets say ( char *strdup(char *) )
char temp[] = "fruit";
char *line = strdup(temp );
I have a small program that creates a semver struct with some variables in it:
typedef struct {
unsigned major;
unsigned minor;
unsigned patch;
char * note;
char * tag;
} semver;
Then, I would like to create a function which creates a semver struct and returns it to the caller. Basically, a Factory.
That factory would call an initialize function to set the default values of the semver struct:
void init_semver(semver * s) {
s->major = 0;
s->minor = 0;
s->patch = 0;
s->note = "alpha";
generate_semver(s->tag, s);
}
And on top of that, I would like a function to generate a string of the complete semver tag.
void generate_semver(char * tag, semver * s) {
sprintf( tag, "v%d.%d.%d-%s",
s->major, s->minor, s->patch, s->note);
}
My problem appears to lie in this function. I have tried returning a string, but have heard that mallocing some space is bad unless you explicitly free it later ;) In order to avoid this problem, I decided to try to pass a string to the function to have it be changed within the function with no return value. I'm trying to loosely follow something like DI practices, even though I'd really like to separate the concerns of these functions and have the generate_semver function return a string that I can use like so:
char * generate_semver(semver * s) {
char * full_semver;
sprintf( full_semver, "v%d.%d.%d-%s",
s->major, s->minor, s->patch, s->note);
return full_semver; // I know this won't work because it is defined in the local stack and not outside.
}
semver->tag = generate_semver(semver);
How can I do this?
My problem appears to lie in this function. I have tried returning a string, but have heard that mallocing some space is bad unless you explicitly free it later.
Explicitly freeing dynamically allocated memory is required to avoid memory leaks. However, it is not necessarily a task that the end users need to perform directly: an API often provides a function to deal with this.
In your case, you should provide a deinit_semver function that does the clean up of memory that init_semver has allocated dynamically. These two functions behave in a way that is similar to constructor and destructor; init_semver is not a factory function, because it expects the semver struct to be allocated, rather than allocating it internally.
Here is one way of doing it:
void init_semver(semver * s, int major, int minor, int pathc, const char * note) {
s->major = major;
s->minor = minor;
s->patch = pathc;
size_t len = strlen(note);
s->note = malloc(len+1);
strcpy(s->note, note);
s->tag = malloc(40 + len);
sprintf(s->tag, "v%d.%d.%d-%s", major, minor, patch, note);
}
void deinit_semver(semver *s) {
free(s->note);
free(s->tag);
}
Note the changes above: rather than using fixed values for the components of struct semver, this code takes the values as parameters. In addition, the code copies the note into a dynamically allocated buffer, rather than pointing to it directly.
The deinit function does the clean-up by free-ing both fields that were allocated dynamically.
A char * on its own is just a pointer to memory. To accomplish what you want you will either need to instead use a fixed size field, i.e. char[33], or you can dynamically allocate the memory as needed.
As it is, your generate_semver function is attempting to print to an unknown address. Let's look at one solution.
typedef struct {
unsigned major;
unsigned minor;
unsigned patch;
char note[32];
char tag[32];
} semver;
Now, in your init_semver function, the line previously s->note = "alpha"; will become a string copy, as arrays are not a valid lvalue.
strncpy(s->note, "alpha", 31);
s->note[31] = '\0';
strncpy will copy a string from the second parameter to the first up to the number of bytes in the third parameter. The second line ensures that a trailing null terminator is in place.
Similarly, in the generate_semver function, it would directly work in the buffer:
void generate_semver(semver * s) {
snprintf( s->tag, 32, "v%d.%d.%d-%s",
s->major, s->minor, s->patch, s->note);
}
This will directly print to the array in the structure, with a maximum character limit. snprintf does append a trailing null terminator (unlike strncpy), so we don't need to worry about adding it ourselves.
You mention having to free allocated memory, and then say: "In order to avoid this problem". Well, it's not so much a problem, but rather a necessity of the C language. It's common to have functions that allocate memory, and require the caller to free it again.
The idiomatic way is to have a pair of "create" and "destroy" functions. So I'd suggest doing it like this:
// Your factory function
semver* create_semver() {
semver* instance = malloc(sizeof(*instance));
init_semver(instance); // will also allocate instance->tag and ->note
return instance;
}
// Your destruction function
void free_semver(semver* s) {
free(semver->tag);
free(semver->note);
free(semver);
}