I am working with a bunch of strings for logging. I want to refactor my code and make a new struct that combines the char, its length and allocated size. The idea is to make my internal string operations smoother and the code nicer to read, whilst assigning each string its own max allocated memory to keep the usage to a minimum but prevent stack overflow. I made this simple example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char *str;
int size;
int max;
} Text;
void defText(Text *text, int max)
{
text->str=(char*) malloc(max * sizeof(char));
text->str="";
text->max=max;
}
int main() {
Text *a;
defText(a,50);
a->str="Test all you want";
printf("OUT: %s %zu %lu",a->str,strlen(a->str),sizeof(a->str));
return 0;
}
The function defText initializes and allocates memory. However, when I check the sizeof the char in my struct, I always get 8, no matter what I set in defText. Is this kind of struct handling strings and their properties together even possible? If so, what is wrong here?
There are several problems in your code, this is an example that cleans up these problems:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char *str;
// you could use size to keep track of the strlen. That's particularly
// desirable if you find yourself calling strlen "a lot", since that
// function recalculates the length every time it's called
int size;
int max;
} Text;
void defText(Text *text, int max)
{
// no need to cast the return of malloc. In fact, sizeof(char) is defined by
// the standard to be 1 so you could take that out also.
text->str=malloc(max * sizeof(char));
// `=` is not the proper way to write strings in C, you must use strcpy
// or something similar. It looks like here you're simply trying to
// create an empty string.
//text->str="";
// per #JohnBollinger's comment, the best thing to do here to create
// an empty string is simply set to the first byte to the NUL
// terminator.
text->str[0] = '\0';
text->max=max;
}
int main() {
Text a; // store this in automatic memory, now the object exists without having to malloc
defText(&a,50); // Use & to pass the address of a to defText
// as mentioned, this is not the proper way to write data to a string in
// C. What you've done here is create a memory leak and point a.str to
// the string literal "Test all you want". Use strcpy (or similar) to
// write that string into the data you actually malloc'ed (using the dot
// operator now since `a` is no longer a pointer)
//a->str="Test all you want";
strcpy(a.str, "Test all you want");
// a.str is a pointer, and will always be 8 bytes on your system no matter
// the size of the memory it points to
printf("OUT: %s %zu %zu",a.str,strlen(a.str),sizeof(a.str));
// clean up allocated memory. Since we're about to exit, there's
// really no need to do this here (the OS will reclaim all allocated
// memory when the process ends), but if you're writing a more
// involved, long-running program, you need to be sure to handle
// memory allocations and deallocations appropriately as needed
free(a.str);
return 0;
}
Demo
The
a->str
is pointer .
the correct answer is
sizeof(*(a->str))
Related
I haven't used C in over 3 years, I'm pretty rusty on a lot of things.
I know this may seem stupid but I cannot return a string from a function at the moment. Please assume that: I cannot use string.h for this.
Here is my code:
#include <ncurses.h>
char * getStr(int length)
{
char word[length];
for (int i = 0; i < length; i++)
{
word[i] = getch();
}
word[i] = '\0';
return word;
}
int main()
{
char wordd[10];
initscr();
*wordd = getStr(10);
printw("The string is:\n");
printw("%s\n",*wordd);
getch();
endwin();
return 0;
}
I can capture the string (with my getStr function) but I cannot get it to display correctly (I get garbage).
Help is appreciated.
Either allocate the string on the stack on the caller side and pass it to your function:
void getStr(char *wordd, int length) {
...
}
int main(void) {
char wordd[10 + 1];
getStr(wordd, sizeof(wordd) - 1);
...
}
Or make the string static in getStr:
char *getStr(void) {
static char wordd[10 + 1];
...
return wordd;
}
Or allocate the string on the heap:
char *getStr(int length) {
char *wordd = malloc(length + 1);
...
return wordd;
}
char word[length];
char *rtnPtr = word;
...
return rtnPtr;
This is not good. You are returning a pointer to an automatic (scoped) variable, which will be destroyed when the function returns. The pointer will be left pointing at a destroyed variable, which will almost certainly produce "strange" results (undefined behaviour).
You should be allocating the string with malloc (e.g. char *rtnPtr = malloc(length)), then freeing it later in main.
You are allocating your string on the stack, and then returning a pointer to it. When your function returns, any stack allocations become invalid; the pointer now points to a region on the stack that is likely to be overwritten the next time a function is called.
In order to do what you're trying to do, you need to do one of the following:
Allocate memory on the heap using malloc or similar, then return that pointer. The caller will then need to call free when it is done with the memory.
Allocate the string on the stack in the calling function (the one that will be using the string), and pass a pointer in to the function to put the string into. During the entire call to the calling function, data on its stack is valid; its only once you return that stack allocated space becomes used by something else.
Your pointer is pointing to local variable of the function. So as soon as you return from the function, memory gets deallocated. You have to assign memory on heap in order to use it in other functions.
Instead
char *rtnPtr = word;
do this
char *rtnPtr = malloc(length);
So that it is available in the main function. After it is used free the memory.
As others already said, you can't return a non-constant string in a useful way without allocating it on the heap (e.g. using strdup). But in all recent versions of the C standard (C89 and later if I'm not mistaken) you can return a struct. It won't be necessary for the caller to deallocate the result because it's not on the heap. And it's thread-safe.
#include <stdio.h>
struct stringbuf
{
char buf[40];
};
struct stringbuf getanswer(int i)
{
struct stringbuf result = { 0 };
snprintf(result.buf, sizeof(result.buf), "The answer is %d", i);
return result;
}
int main(int argc, char **argv)
{
/*
* Remember to pass the .buf member, not the struct, to functions
* such as printf which expect a character pointer as argument!
* Passing the result of getanswer in the next line without .buf
* appended, will likely crash the program because the program
* will put the entire struct on the stack, not a character
* pointer, and will make printf interpret the first few bytes
* of the string as a pointer. That would be bad.
*/
printf("How many arguments did I get? %s\n", getanswer(argc).buf);
return 0;
}
Note: To keep the sample code as simple and focused as possible, I simply declared a struct type without typedef. You may save yourself a lot of typing by using typedef and returning the defined type.
There are (arguably) a few disadvantages:
A function that returns a struct cannot return NULL.
The size of the buffer in the struct is fixed because the compiler has to know the size of the return type at compile time.
The result of a function that returns a struct is probably stored on the stack; this may be a problem in small systems (like microcontrollers) that don't have a lot of stack space.
Unlike character arrays, an instance of a struct is not a usable alias for the string that's stored in it. In other words, whereas you can create an array of characters and use its name as a pointer to the first character, you can't use the name of a struct as a pointer.
That last point is important because you have to keep in mind that a struct with a character array is not the same as the array itself. So if you want to call a string function, you should pass the string member variable, not a pointer to the struct. This is especially important for functions with variadic arguments such as printf and friends where a compiler may not warn you if you're doing it wrong: passing a struct will place the entire struct on the stack, not just a pointer to the first character. Printf will interpret the first few characters in the struct as a character pointer, which will certainly be invalid.
Yes, it's possible to cast a pointer to a struct to a char * and pass it to a string function (including printf) and that will work correctly, but I would argue that it's bad practice to do this: If you (or someone else) ever decides to put another member variable in the struct declaration in front of the string buffer, any use of a typecast pointer to a struct that assumes that the string buffer starts where the struct starts, would silently fail. You probably want to avoid this, so use a pointer to the string member variable even if it's somewhat inconvenient.
===Jac
word is on the stack and goes out of scope as soon as getStr() returns. You are invoking undefined behavior.
I came across this thread while working on my understanding of Cython. My extension to the original question might be of use to others working at the C / Cython interface. So this is the extension of the original question: how do I return a string from a C function, making it available to Cython & thus to Python?
For those not familiar with it, Cython allows you to statically type Python code that you need to speed up. So the process is, enjoy writing Python :), find its a bit slow somewhere, profile it, calve off a function or two and cythonize them. Wow. Close to C speed (it compiles to C) Fixed. Yay. The other use is importing C functions or libraries into Python as done here.
This will print a string and return the same or another string to Python. There are 3 files, the c file c_hello.c, the cython file sayhello.pyx, and the cython setup file sayhello.pyx. When they are compiled using python setup.py build_ext --inplace they generate a shared library file that can be imported into python or ipython and the function sayhello.hello run.
c_hello.c
#include <stdio.h>
char *c_hello() {
char *mystr = "Hello World!\n";
return mystr;
// return "this string"; // alterative
}
sayhello.pyx
cdef extern from "c_hello.c":
cdef char* c_hello()
def hello():
return c_hello()
setup.py
from setuptools import setup
from setuptools.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize
ext_modules = cythonize([Extension("sayhello", ["sayhello.pyx"])])
setup(
name = 'Hello world app',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)
Easier still: return a pointer to a string that's been malloc'd with strdup.
#include <ncurses.h>
char * getStr(int length)
{
char word[length];
for (int i = 0; i < length; i++)
{
word[i] = getch();
}
word[i] = '\0';
return strdup(&word[0]);
}
int main()
{
char wordd[10];
initscr();
*wordd = getStr(10);
printw("The string is:\n");
printw("%s\n",*wordd);
getch();
endwin();
return 0;
}
I haven't used C in over 3 years, I'm pretty rusty on a lot of things.
I know this may seem stupid but I cannot return a string from a function at the moment. Please assume that: I cannot use string.h for this.
Here is my code:
#include <ncurses.h>
char * getStr(int length)
{
char word[length];
for (int i = 0; i < length; i++)
{
word[i] = getch();
}
word[i] = '\0';
return word;
}
int main()
{
char wordd[10];
initscr();
*wordd = getStr(10);
printw("The string is:\n");
printw("%s\n",*wordd);
getch();
endwin();
return 0;
}
I can capture the string (with my getStr function) but I cannot get it to display correctly (I get garbage).
Help is appreciated.
Either allocate the string on the stack on the caller side and pass it to your function:
void getStr(char *wordd, int length) {
...
}
int main(void) {
char wordd[10 + 1];
getStr(wordd, sizeof(wordd) - 1);
...
}
Or make the string static in getStr:
char *getStr(void) {
static char wordd[10 + 1];
...
return wordd;
}
Or allocate the string on the heap:
char *getStr(int length) {
char *wordd = malloc(length + 1);
...
return wordd;
}
char word[length];
char *rtnPtr = word;
...
return rtnPtr;
This is not good. You are returning a pointer to an automatic (scoped) variable, which will be destroyed when the function returns. The pointer will be left pointing at a destroyed variable, which will almost certainly produce "strange" results (undefined behaviour).
You should be allocating the string with malloc (e.g. char *rtnPtr = malloc(length)), then freeing it later in main.
You are allocating your string on the stack, and then returning a pointer to it. When your function returns, any stack allocations become invalid; the pointer now points to a region on the stack that is likely to be overwritten the next time a function is called.
In order to do what you're trying to do, you need to do one of the following:
Allocate memory on the heap using malloc or similar, then return that pointer. The caller will then need to call free when it is done with the memory.
Allocate the string on the stack in the calling function (the one that will be using the string), and pass a pointer in to the function to put the string into. During the entire call to the calling function, data on its stack is valid; its only once you return that stack allocated space becomes used by something else.
Your pointer is pointing to local variable of the function. So as soon as you return from the function, memory gets deallocated. You have to assign memory on heap in order to use it in other functions.
Instead
char *rtnPtr = word;
do this
char *rtnPtr = malloc(length);
So that it is available in the main function. After it is used free the memory.
As others already said, you can't return a non-constant string in a useful way without allocating it on the heap (e.g. using strdup). But in all recent versions of the C standard (C89 and later if I'm not mistaken) you can return a struct. It won't be necessary for the caller to deallocate the result because it's not on the heap. And it's thread-safe.
#include <stdio.h>
struct stringbuf
{
char buf[40];
};
struct stringbuf getanswer(int i)
{
struct stringbuf result = { 0 };
snprintf(result.buf, sizeof(result.buf), "The answer is %d", i);
return result;
}
int main(int argc, char **argv)
{
/*
* Remember to pass the .buf member, not the struct, to functions
* such as printf which expect a character pointer as argument!
* Passing the result of getanswer in the next line without .buf
* appended, will likely crash the program because the program
* will put the entire struct on the stack, not a character
* pointer, and will make printf interpret the first few bytes
* of the string as a pointer. That would be bad.
*/
printf("How many arguments did I get? %s\n", getanswer(argc).buf);
return 0;
}
Note: To keep the sample code as simple and focused as possible, I simply declared a struct type without typedef. You may save yourself a lot of typing by using typedef and returning the defined type.
There are (arguably) a few disadvantages:
A function that returns a struct cannot return NULL.
The size of the buffer in the struct is fixed because the compiler has to know the size of the return type at compile time.
The result of a function that returns a struct is probably stored on the stack; this may be a problem in small systems (like microcontrollers) that don't have a lot of stack space.
Unlike character arrays, an instance of a struct is not a usable alias for the string that's stored in it. In other words, whereas you can create an array of characters and use its name as a pointer to the first character, you can't use the name of a struct as a pointer.
That last point is important because you have to keep in mind that a struct with a character array is not the same as the array itself. So if you want to call a string function, you should pass the string member variable, not a pointer to the struct. This is especially important for functions with variadic arguments such as printf and friends where a compiler may not warn you if you're doing it wrong: passing a struct will place the entire struct on the stack, not just a pointer to the first character. Printf will interpret the first few characters in the struct as a character pointer, which will certainly be invalid.
Yes, it's possible to cast a pointer to a struct to a char * and pass it to a string function (including printf) and that will work correctly, but I would argue that it's bad practice to do this: If you (or someone else) ever decides to put another member variable in the struct declaration in front of the string buffer, any use of a typecast pointer to a struct that assumes that the string buffer starts where the struct starts, would silently fail. You probably want to avoid this, so use a pointer to the string member variable even if it's somewhat inconvenient.
===Jac
word is on the stack and goes out of scope as soon as getStr() returns. You are invoking undefined behavior.
I came across this thread while working on my understanding of Cython. My extension to the original question might be of use to others working at the C / Cython interface. So this is the extension of the original question: how do I return a string from a C function, making it available to Cython & thus to Python?
For those not familiar with it, Cython allows you to statically type Python code that you need to speed up. So the process is, enjoy writing Python :), find its a bit slow somewhere, profile it, calve off a function or two and cythonize them. Wow. Close to C speed (it compiles to C) Fixed. Yay. The other use is importing C functions or libraries into Python as done here.
This will print a string and return the same or another string to Python. There are 3 files, the c file c_hello.c, the cython file sayhello.pyx, and the cython setup file sayhello.pyx. When they are compiled using python setup.py build_ext --inplace they generate a shared library file that can be imported into python or ipython and the function sayhello.hello run.
c_hello.c
#include <stdio.h>
char *c_hello() {
char *mystr = "Hello World!\n";
return mystr;
// return "this string"; // alterative
}
sayhello.pyx
cdef extern from "c_hello.c":
cdef char* c_hello()
def hello():
return c_hello()
setup.py
from setuptools import setup
from setuptools.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize
ext_modules = cythonize([Extension("sayhello", ["sayhello.pyx"])])
setup(
name = 'Hello world app',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)
Easier still: return a pointer to a string that's been malloc'd with strdup.
#include <ncurses.h>
char * getStr(int length)
{
char word[length];
for (int i = 0; i < length; i++)
{
word[i] = getch();
}
word[i] = '\0';
return strdup(&word[0]);
}
int main()
{
char wordd[10];
initscr();
*wordd = getStr(10);
printw("The string is:\n");
printw("%s\n",*wordd);
getch();
endwin();
return 0;
}
I have a string function that accepts a pointer to a source string and returns a pointer to a destination string. This function currently works, but I'm worried I'm not following the best practice regrading malloc, realloc, and free.
The thing that's different about my function is that the length of the destination string is not the same as the source string, so realloc() has to be called inside my function. I know from looking at the docs...
http://www.cplusplus.com/reference/cstdlib/realloc/
that the memory address might change after the realloc. This means I have can't "pass by reference" like a C programmer might for other functions, I have to return the new pointer.
So the prototype for my function is:
//decode a uri encoded string
char *net_uri_to_text(char *);
I don't like the way I'm doing it because I have to free the pointer after running the function:
char * chr_output = net_uri_to_text("testing123%5a%5b%5cabc");
printf("%s\n", chr_output); //testing123Z[\abc
free(chr_output);
Which means that malloc() and realloc() are called inside my function and free() is called outside my function.
I have a background in high level languages, (perl, plpgsql, bash) so my instinct is proper encapsulation of such things, but that might not be the best practice in C.
The question: Is my way best practice, or is there a better way I should follow?
full example
Compiles and runs with two warnings on unused argc and argv arguments, you can safely ignore those two warnings.
example.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *net_uri_to_text(char *);
int main(int argc, char ** argv) {
char * chr_input = "testing123%5a%5b%5cabc";
char * chr_output = net_uri_to_text(chr_input);
printf("%s\n", chr_output);
free(chr_output);
return 0;
}
//decodes uri-encoded string
//send pointer to source string
//return pointer to destination string
//WARNING!! YOU MUST USE free(chr_result) AFTER YOU'RE DONE WITH IT OR YOU WILL GET A MEMORY LEAK!
char *net_uri_to_text(char * chr_input) {
//define variables
int int_length = strlen(chr_input);
int int_new_length = int_length;
char * chr_output = malloc(int_length);
char * chr_output_working = chr_output;
char * chr_input_working = chr_input;
int int_output_working = 0;
unsigned int uint_hex_working;
//while not a null byte
while(*chr_input_working != '\0') {
//if %
if (*chr_input_working == *"%") {
//then put correct char in
sscanf(chr_input_working + 1, "%02x", &uint_hex_working);
*chr_output_working = (char)uint_hex_working;
//printf("special char:%c, %c, %d<\n", *chr_output_working, (char)uint_hex_working, uint_hex_working);
//realloc
chr_input_working++;
chr_input_working++;
int_new_length -= 2;
chr_output = realloc(chr_output, int_new_length);
//output working must be the new pointer plys how many chars we've done
chr_output_working = chr_output + int_output_working;
} else {
//put char in
*chr_output_working = *chr_input_working;
}
//increment pointers and number of chars in output working
chr_input_working++;
chr_output_working++;
int_output_working++;
}
//last null byte
*chr_output_working = '\0';
return chr_output;
}
It's perfectly ok to return malloc'd buffers from functions in C, as long as you document the fact that they do. Lots of libraries do that, even though no function in the standard library does.
If you can compute (a not too pessimistic upper bound on) the number of characters that need to be written to the buffer cheaply, you can offer a function that does that and let the user call it.
It's also possible, but much less convenient, to accept a buffer to be filled in; I've seen quite a few libraries that do that like so:
/*
* Decodes uri-encoded string encoded into buf of length len (including NUL).
* Returns the number of characters written. If that number is less than len,
* nothing is written and you should try again with a larger buffer.
*/
size_t net_uri_to_text(char const *encoded, char *buf, size_t len)
{
size_t space_needed = 0;
while (decoding_needs_to_be_done()) {
// decode characters, but only write them to buf
// if it wouldn't overflow;
// increment space_needed regardless
}
return space_needed;
}
Now the caller is responsible for the allocation, and would do something like
size_t len = SOME_VALUE_THAT_IS_USUALLY_LONG_ENOUGH;
char *result = xmalloc(len);
len = net_uri_to_text(input, result, len);
if (len > SOME_VALUE_THAT_IS_USUALLY_LONG_ENOUGH) {
// try again
result = xrealloc(input, result, len);
}
(Here, xmalloc and xrealloc are "safe" allocating functions that I made up to skip NULL checks.)
The thing is that C is low-level enough to force the programmer to get her memory management right. In particular, there's nothing wrong with returning a malloc()ated string. It's a common idiom to return mallocated obejcts and have the caller free() them.
And anyways, if you don't like this approach, you can always take a pointer to the string and modify it from inside the function (after the last use, it will still need to be free()d, though).
One thing, however, that I don't think is necessary is explicitly shrinking the string. If the new string is shorter than the old one, there's obviously enough room for it in the memory chunk of the old string, so you don't need to realloc().
(Apart from the fact that you forgot to allocate one extra byte for the terminating NUL character, of course...)
And, as always, you can just return a different pointer each time the function is called, and you don't even need to call realloc() at all.
If you accept one last piece of good advice: it's advisable to const-qualify your input strings, so the caller can ensure that you don't modify them. Using this approach, you can safely call the function on string literals, for example.
All in all, I'd rewrite your function like this:
char *unescape(const char *s)
{
size_t l = strlen(s);
char *p = malloc(l + 1), *r = p;
while (*s) {
if (*s == '%') {
char buf[3] = { s[1], s[2], 0 };
*p++ = strtol(buf, NULL, 16); // yes, I prefer this over scanf()
s += 3;
} else {
*p++ = *s++;
}
}
*p = 0;
return r;
}
And call it as follows:
int main()
{
const char *in = "testing123%5a%5b%5cabc";
char *out = unescape(in);
printf("%s\n", out);
free(out);
return 0;
}
It's perfectly OK to return newly-malloc-ed (and possibly internally realloced) values from functions, you just need to document that you are doing so (as you do here).
Other obvious items:
Instead of int int_length you might want to use size_t. This is "an unsigned type" (usually unsigned int or unsigned long) that is the appropriate type for lengths of strings and arguments to malloc.
You need to allocate n+1 bytes initially, where n is the length of the string, as strlen does not include the terminating 0 byte.
You should check for malloc failing (returning NULL). If your function will pass the failure on, document that in the function-description comment.
sscanf is pretty heavy-weight for converting the two hex bytes. Not wrong, except that you're not checking whether the conversion succeeds (what if the input is malformed? you can of course decide that this is the caller's problem but in general you might want to handle that). You can use isxdigit from <ctype.h> to check for hexadecimal digits, and/or strtoul to do the conversion.
Rather than doing one realloc for every % conversion, you might want to do a final "shrink realloc" if desirable. Note that if you allocate (say) 50 bytes for a string and find it requires only 49 including the final 0 byte, it may not be worth doing a realloc after all.
I would approach the problem in a slightly different way. Personally, I would split your function in two. The first function to calculate the size you need to malloc. The second would write the output string to the given pointer (which has been allocated outside of the function). That saves several calls to realloc, and will keep the complexity the same. A possible function to find the size of the new string is:
int getNewSize (char *string) {
char *i = string;
int size = 0, percent = 0;
for (i, size; *i != '\0'; i++, size++) {
if (*i == '%')
percent++;
}
return size - percent * 2;
}
However, as mentioned in other answers there is no problem in returning a malloc'ed buffer as long as you document it!
Additionally what was already mentioned in the other postings, you should also document the fact that the string is reallocated. If your code is called with a static string or a string allocated with alloca, you may not reallocate it.
I think you are right to be concerned about splitting up mallocs and frees. As a rule, whatever makes it, owns it and should free it.
In this case, where the strings are relatively small, one good procedure is to make the string buffer larger than any possible string it could contain. For example, URLs have a de facto limit of about 2000 characters, so if you malloc 10000 characters you can store any possible URL.
Another trick is to store both the length and capacity of the string at its front, so that (int)*mystring == length of string and (int)*(mystring + 4) == capacity of string. Thus, the string itself only starts at the 8th position *(mystring+8). By doing this you can pass around a single pointer to a string and always know how long it is and how much memory capacity the string has. You can make macros that automatically generate these offsets and make "pretty code".
The value of using buffers this way is you do not need to do a reallocation. The new value overwrites the old value and you update the length at the beginning of the string.
I need a working code for a function that will return a random string with a random length.
What I want to do would be better described by the following code.
char *getRandomString()
{
char word[random-length];
// ...instructions that will fill word with random characters.
return word;
}
void main()
{
char *string = getRandomString();
printf("Random string is: %s\n", string);
}
For this, I am strictly forbidden to use any other include than stdio.h.
Edit: This project will be adapted to be compiled for a PIC Microcontroller, hence I cannot use malloc() or such stuff.
The reason why I use stdio.h here, is for me to be able to inspect the output using GCC.
Currently, this code gives this error.-
“warning: function returns address of local variable [enabled by default]”
Then, I thought this could work.-
char *getRandomString(char *string)
{
char word[random-length];
// ...instructions that will fill word with random characters.
string = word;
return string;
}
void main()
{
char *string = getRandomString(string);
printf("Random string is: %s\n", string);
}
But it only prints a bunch of nonsense characters.
There are three common ways to do this.
Have the caller pass in a pointer to (the first element of) an array into which the data is to be stored, along with a length parameter. If the string to be returned is bigger than the passed-in length, it's an error; you need to decide how to deal with it. (You could truncate the result, or you could return a null pointer. Either way, the caller has to be able to deal with it.)
Return a pointer to a newly allocated object, making it the caller's responsibility to call free when done. Probably return a null pointer if malloc() fails (this is always a possibility, and you should always check for it). Since malloc and free are declared in <stdlib.h> this doesn't meet your (artificial) requirements.
Return a pointer to (the first element of) a static array. This avoids the error of returning a pointer to a locally allocated object, but it has its own drawbacks. It means that later calls will clobber the original result, and it imposes a fixed maximum size.
None if these is an ideal solution.
It points to nonsense characters because you are returning local address. char word[random-length]; is defined local to char *getRandomString(char *string)
Dynamically allocate the string with malloc, populate string, and return the returned address by malloc. This returned address is allocated from the heap and will be allocated until you do not manually free it (or the program does not terminate).
char *getRandomString(void)
{
char *word;
word = malloc (sizeof (random_length));
// ...instructions that will fill word with random characters.
return word;
}
After you have done with the allocated string, remember to free the string.
Or another thing can be done, if you cannot use malloc which is define the local string in the getRandomString as static which makes the statically declared array's lifetime as long as the program runs.
char *getRandomString(void)
{
static char word[LENGTH];
// ...instructions that will fill word with random characters.
return word;
}
Or simply make the char word[128]; global.
As I understand, malloc is not an option.
Write a couple of functions to a) get a random integer (strings length), and b)a random char.
Then use those to build your random string.
For example:
//pseudocode
static char random_string[MAX_STRING_LEN];
char *getRandomString()
{
unsigned int r = random_number();
for (i=0;i<r;i++){
random_string[i] = random_char();
}
random_string[r-1] = '\0';
}
If you are not allowed to use malloc you'll have to declare an array that can be the maximum possible size at file scope and fill it with random characters.
#define MAX_RANDOM_STRING_LENGTH 1024
char RandomStringArray[MAX_RANDOM_STRING_LENGTH];
char *getRandomString(size_t length)
{
if( length > ( MAX_RANDOM_STRING_LENGTH - 1 ) ) {
return NULL; //or handle this condition some other way
} else {
// fill 'length' bytes in RandomStringArray with random characters.
RandomStringArray[length] = '\0';
return &RandomStringArray[0];
}
}
int main()
{
char *string = getRandomString(100);
printf("Random string is: %s\n", string);
return 0;
}
Both of your examples are returning pointers to local variables - that's generally a no-no. You won't be able to create memory for your caller to use without malloc(), which isn't defined in stdio.h, so I guess your only option is to make word static or global, unless you can declare it in main() and pass the pointer to your random string function to be filled in. How are you generating random numbers with only the functions in stdio.h?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num = 1;
char* test[8];
sprintf(test[0],"%d",num);
printf("%s\n",test[0]);
}
char *test[8] is an array of 8 char *, or pointers to strings, and since you don't specify, they're all set to garbage values. So sprintf is trying to write data to who-knows-where.
You should use char test[8] instead, which allocates an array of 8 char, and then sprintf(test, "%d", num);.
UPDATE: If you want to use char * pointers, you should allocate space:
char *test = malloc(8 /* see note below */);
sprintf(test, "%d", num);
If you want to use an array of char * pointers, it works the same:
char *test[8]; // 8 pointers to strings
test[0] = malloc(8); // allocate memory for the first pointer
sprintf(test[0], "%d", num);
Keep in mind you would have to call malloc for each of test[0] through test[7] individually.
Also, as mentioned in the comments, if your compiler supports it you should use snprintf(). It's like sprintf but it takes an extra parameter which is the size of the buffer:
snprintf(test, 8, "%d", num);
and guarantees not to use more space than you allow it. It's safer, and if you need to, snprintf returns the amount of space it actually wanted, so if you gave it too little room you can realloc and try again.
Note: some will say this should be malloc(8 * sizeof(char)) (or sizeof *test). They are wrong (in my objectively-correct opinion; note the sarcasm)! sizeof(char) is guaranteed to be 1, so this multiplication is unnecessary.
Some advocate the usage of TYPE *p = malloc(x * sizeof *p) so that if TYPE changes, you'll only need to change it in one place, and sizeof *p will adapt. I am one of these people, but in my opinion you will rarely need to upgrade a char * to another type. Since so many functions use char * and would need to be changed in such an upgrade, I'm not worried about making malloc lines more flexible.
sprintf() does not allocate space for the string; you must do that yourself beforehand.
Look at your warnings:
test.c: In function ‘main’:
test.c:8: warning: ‘test[0]’ is used uninitialized in this function
You allocate an array of 8 pointers, but use one without initializing it. You must call malloc and store the result in test[0] before you can write to the memory pointed to by test[0]. You free it at the end.
A useful function, present in GNU and BSD, is asprintf, which will call malloc for you to allocate enough memory for the formatted string:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int num = 1;
char* test[8];
asprintf(&test[0],"%d",num);
printf("%s\n",test[0]);
free(test[0]);
return 0;
}
(Note that you pass the address of your pointer to asprintf — since your pointer is test[0], its address is &test[0].)
You did allocate space but you you are passing the wrong thing. Try this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num = 1;
char test[8];
sprintf(test,"%d",num);
printf("%s\n",test);
}
int main()
{
char *str[5];
sprintf(str[0], "%d",55);
printf("%s\n",str[0]);
return 0;
}
This will be work. But, if you specify variable instead of integer constant value show the segmentation fault will be occur. This error will be happened at the time of sprintf function execution. Because user space memory access.