How do I convert a buffer to a binary string in c++? - c

I am trying to convert an arbitrary buffer to a string of its binary representation. I was looking at some code from here: http://snippets.dzone.com/posts/show/2076 in order to get started. I realize that this code can not convert an arbitrary buffer, but only the specific case of an int; however, I figured that I could adapt it to any case once it was working.
The problem is that it returns some strange symbols (like this: �왿") instead of the binary. Does anyone either know what is wrong with this code specifically or explain how to convert an arbitrary buffer?
Please keep in mind that I am new to c++.
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
char *getBufferAsBinaryString(void *in)
{
int pos=0;
char result;
char bitstring[256];
memset(bitstring, 0, 256);
unsigned int *input= (unsigned int *)in;
for(int i=31;i>=0;i--)
{
if (((*input >> i) & 1)) result = '1';
else result = '0';
bitstring[pos] = result;
if ((i>0) && ((i)%4)==0)
{
pos++;
bitstring[pos] = ' ';
}
pos++;
}
return bitstring;
}
int main(int argc, char* argv[])
{
int i=53003;
char buffer[1024];
char *s=getBufferAsBinaryString(&i);
strcpy(buffer, s);
printf("%s\n", buffer);
}

The array bitstring has what is known as automatic duration, which means that it springs into existence when the function is called and disappears when the function returns.
Therefore, the pointer that this version of getBufferAsBinaryString returns is to an array which no longer exists by the time the caller receives the pointer. (Remember that the statement return bitstring; returns a pointer to the first character in bitstring; by the "equivalence of arrays and pointers," the mention of the array bitstring in this context is equivalent to &bitstring[0].)
When the caller tries to use the pointer, the string created by getBufferAsBinaryString might still be there, or the memory might have been re-used by some other function. Therefore, this version of getBufferAsBinaryString is not adequate and not acceptable. Functions must never return pointers to local, automatic-duration arrays.
Since the problem with returning a pointer to a local array is that the array has automatic duration by default, the simplest fix to the above non-functional version of getBufferAsBinaryString is to declare the array static, instead:
char *getBufferAsBinaryString(void *in)
{
int pos=0;
char result;
static char bitstring[256];
memset(bitstring, 0, 256);
unsigned int *input= (unsigned int *)in;
for(int i=31;i>=0;i--)
{
if (((*input >> i) & 1)) result = '1';
else result = '0';
bitstring[pos] = result;
if ((i>0) && ((i)%4)==0)
{
pos++;
bitstring[pos] = ' ';
}
pos++;
}
return bitstring;
}
Now, the bitstring array does not disappear when getBufferAsBinaryString returns, so the pointer is still valid by the time the caller uses it.
Returning a pointer to a static array is a practical and popular solution to the problem of "returning" an array, but it has one drawback. Each time you call the function, it re-uses the same array and returns the same pointer. Therefore, when you call the function a second time, whatever information it "returned" to you last time will be overwritten. (More precisely, the information, that the function returned a pointer to, will be overwritten.)
Although the static return array technique will work, the caller has to be a little bit careful, and must never expect the return pointer from one call to the function to be usable after a later call to the function
But you still have a different problem with passing in void * which I did not cover, in addition not passing in the size of your buffer. Since you shouldn't assume that your array ends in the \0, you should also pass in the size of your buffer.

Ignoring the other issues with memory and safety, you are not returning a valid null terminated string. Nor do you pass in the size of the input buffer, so you really just print out the 32-bit bit representation of the first 32-bits of the input buffer.
So, in addition to passing in a char buffer to write to or simply returning a std::string, you should also pass in the size of the input buffer and loop over that as well.

You can't return locally-allocated arrays from a function. As soon as the function finishes, the array ceases to exist, so the pointer you've returned no longer points to a valid object.
Instead of using a char array to represent your bitstring, you should consider using std::string, which has sensible value semantics (i.e., you can copy it, return it from a function, etc, without having to worry about it except from an efficiency standpoint).

Related

Why can I return `int` after a function but not `char *`?

I'm a newbie to C. I had extended the question from the previous question: Strange behavior when returning "string" with C (Thanks for all who answered or commented that question, by the way.)
Pretty straight forward:
Why can this work:
#include <stdio.h>
int func() {
int i = 5;
return i;
}
int main() {
printf("%d",func());
}
But not this:
#include <stdio.h>
char * func() {
char c[] = "Hey there!";
return c;
}
int main() {
printf("%s",func());
}
From the previous question, logically the int i should not exist too because the function has returned, but why can it still be returned while char c[] cannot?
(It seems to be duplicated from "Pointers and memory scope" but I would like to know more about what is the difference between returning an int and a char *.)
Problem is not returning char *, it is returning something that is allocated on stack.
If you allocate memory for your string rather than pointing to function stack, there will be no problem. Something like this:
char * func() {
char c[] = "Hey there!";
return strdup(c);
}
int main() {
char* str = func();
printf("%s", str);
free(str);
}
It is important to mention that in both cases, you are copying a value and in both cases copied value is correct, but the meaning of copied value differs.
In first case, your are copying an int value and after your return from function, you are using that int value which will be valid. But in 2nd case, even though you have a valid pointer value, it refers to an invalid address of memory which is stack of called function.
Based on suggestions in comment, I decided to add another better practice in memory allocating for this code:
#define NULL (void*)0
int func(char *buf, int len) {
char c[] = "Hey there!";
int size = strlen(c) + 1;
if (len >= size) {
strcpy(buf, c);
}
return size;
}
int main() {
int size = func(NULL, 0);
char *buf = calloc(size, sizeof(*buf));
func(buf, size);
printf("%s", buf);
free(buf);
return 0;
}
Similar approach is used in a lot of windows API functions. This approach is better, because owner of pointer is more obvious (main in here).
In the first example the return value is copied. In your second example you're returning a pointer, which will point to a memory location which no longer exists.
In the first case, you return the int value 5 from the function. You can then print that value.
In the second case however, you return a value of type char *. That value points to an array that is local to the function func. After that function returns the array goes out of scope, so the pointer points to invalid memory.
The difference between these two cases is a value that you use directly, versus a pointer value that no longer points to valid memory. Had you returned a pointer to memory allocated by malloc, then the pointer would point to valid memory.
You are trying to return pointer to local array, which is very bad. If you want to return a pointer to array, allocate it dynamically using malloc inside your func();
Then you must call free() on caller side to free up memory you allocated when you no longer need it
In the first example, you return an int, and the second you return a pointer to a char. They both return in exactly the same manner, it is just a matter of understanding the stack and how values are returned.
Even though i was declared in the function and is allocated on the stack, when the function returns it returns the value of i (which is basically copied, so when i falls off the stack the value of i is still returned.)
This is the exact same thing that happens to the char * in the second example. It will still be a pointer to a char, and it returns the 'copied' value of c. However, since it was allocated on the stack, the address it points to is effectively invalid. The pointer value itself has not changed, but what it points to has.
You would have to dynamically allocate this to avoid this situation.
The return value of function is returned by copy. In the first example, you get a copy of the integer variable from the function. In the second you get a copy of the char pointer, not a copy of the string.
The pointer references the string data that has automatic storage, so is no longer valid after the function returns. The space becomes available for use by other code and many be modified - any attempt to access it has undefined behaviour.
The point is, it is a pointer that is returned, not a string; in C a strings (and more generally arrays) are not a first-class data types.
Depending on your needs there are a number of valid ways of returning the string data; for example the following is valid:
char* func()
{
static char c[] = "Hey there!";
return c;
}
because here although the local variable goes out of scope the static data is not destroyed or de-allocated, and any reference to it remains valid.
Another alternative is to embed the string in a struct which is a first-class data type:
typedef struct
{
char content[256] ;
} sString ;
sString func()
{
sString c = {"Hey there!"};
return c;
}
Or more conventionally to copy the data to a caller buffer:
char* func( char* buffer )
{
char c[] = "Hey there!";
strcpy( buffer, c ) ;
return buffer ;
}
I have omitted code to mitigate the possibility of buffer overrun above for clarity in this last example, such code is advised.

Receive an array of strings from a function and find out it's length [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have this code:
char** SplitToWords(char* str);
int main()
{
char** wordarr;
char str[] = "This is a sentence";
wordarr = SplitToWords(str);
return 0;
}
After the main comes the function implementation.
I am not sure the following does what I want it to do (i.e. receive an array of strings from a function):
wordarr = SplitToWords(str);
I somehow managed to convince the compiler that it's ok, but I assume it just does something else.
If it does, how do I find out the length of the array (the number of strings in it).
Thanks
I'll try to quickly visit all aspects you might not yet fully understand:
A string in C is described as a contiguous sequence of chars, ending with a char of value 0 (as a literal: '\0'). It is not a first class object, therefore hasn't its own type. So what you use to hold a string is an array of char. Therefore, taking your question by the word, "receive an array of strings from a function" is not possible.
An array is a contiguous sequence of objects of the same type. In C, the identifier of an array doesn't have a value itself; when it's evaluated, it decays as a pointer to the array's first element instead. This is especially important when passing arrays to functions or returning them from functions -- you can't actually pass the array, you always pass a pointer
e.g. you could write:
char x[] = "foo"; // initialize a char array from a string literal
char *xp = x; // here, x evaluates as a pointer to the first element of the array
You already use pointer types for your function's argument and return value, I just think it's quite important to understand what happens entirely.
You write char** SplitToWords(char* str); and ask whether this returns an "array of strings" -- well, sort of, as you should understand after reading 1. and 2. -- What it does is returning a pointer to char *. This pointer could be a pointer to the first element of an array. So in this case, it would return a pointer to an array of char * pointers. Each of these pointers could itself be a pointer to an array of chars, therefore point to a string. But what's very important is to understand you never return an array, you always return a pointer to it. It's so important because:
You might get the idea to do something like this:
char** SplitToWords(char* str)
{
char *words[16];
// code to fill `words` with pointers to the actual words
return words; // WRONG!
}
Here, because you're not returning the array words but a pointer to it (see point 2), you return a pointer to an object that no longer exists. words is in the scope of your function and has automatic storage duration, that means it only lives as long as the execution is inside of the function. One solution would be to declare words with the static storage class specifier. This way, it lives for the entire execution time of the program. But be aware that this also means there's only a single instance ever, it's always the same object. This will be a major headache for threaded programs, for example. The other way around is to dynamically allocate words using malloc(). But then, the caller of the function must free() it later.
As for your second question, how to let the caller know the number of words -- it's in the comments already, but just for completeness, a typical approach to solve this is to append another entry that is a NULL pointer. So the caller can iterate over the pointers until it finds NULL.
Regarding your comment, of course you can create the array outside the function and pass a pointer to the function, so the function only fills it. This is a common idiom in C (e.g. think about fgets(), which takes a pointer to the char array that's filled with a string by the function).
Functions working this way will need an additional size_t parameter, so they know the size of the array they should fill through the pointer, otherwise you'd have the risk of buffer overflows (this is why gets() was finally removed from the C standard). If you decide that the caller provides the storage, your function should have this prototype:
// returns the number of words found, up to `nwords`
size_t SplitToTwords(char **words, size_t nwords, char *str);
It should be called e.g. like this:
char *words[16];
size_t nwords = SplitToWords(words, 16, "the quick brown fox"); // returns 4
Remember that the strings holding the words themselves need storage as well. You can either manipulate the bytes in str to insert a '\0' after each word, overwriting the first whitespace character (this is what strtok() does) or you can copy the words to new strings, but then you would have to malloc() each of them again and the caller has to free() them later.
Yes, you could solve it by using a function with return value char **. However, there's no way to find out how many words there are afterwards.
You can solve this by allocating one more element for the return pointer and set it to NULL. Then you can get the number of words with this code:
wordarr = SplitToWords(str);
char **ptr=wordarr;
int noWords=0;
while(!*(ptr+noWords))
noWords++;
But if you want to return multiple data in C, you either need to define a return struct or using return arguments. In this case, it could look like this for the first option:
typedef struct wordList {
char **wordarr;
int noWords;
}
wordList SplitToWords(char* str);
And the second:
char** SplitToWords(char* str, int *noWords);
or
void SplitToWords(char* str, char*** wordarr, int *noWords);
Note that there's three *. That's because we want it to be a pointer to char **
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSTRINGS 5000
int main(int argc, char *argv[]) {
char *stringTable[MAXSTRINGS];
char sentence[] = "This is a sentence";
char *token = NULL;
int i = 0;
while ((token = strtok(token == NULL ? sentence : NULL, " ")) != NULL)
{
printf("%s\n\r", token);
stringTable[i] = (char *)malloc(strlen(token) + 1); //have no "plain" C compiler - VS C++ used so cast needed :)
strcpy(stringTable[i++], token);
}
stringTable[i] = NULL; // if you need to iterate through later
printf("%d tokens found\n\r", i);
for (int y = 0; y < i; y++)
free(stringTable[y]);
}

Returing and printing a string from a function in C

I am trying to return and print a function in C. Printing it out works in the function just fine, but when I try to print it after returning it from the function, I get nonsense.
I have already tried a lot and I think I have seen at least 6 stack overflow posts similar to this and this is the closest thing I can get to working that is not a segmentation fault or an error.
Code:
char* getBitstring(unsigned short int instr) {
//this is what the code below is going to convert into. It is set to default
//as a 16 bit string full of zeros to act as a safety default.
char binaryNumber[] = "0000000000000000";
//....
//doing things to binaryNumber
//.....
printf("don't get excited yet %s\n", binaryNumber); //note, this works
return binaryNumber;
}
int main(int argc, char *argv[]) {
char *a = getBitstring(0x1234);
printf("%s", a); //this fails
return 0;
}
Here is the output:
don't get excited yet 0001001000110100
������e��r�S�����$�r�#�t�$�r�����ͅS�������t����
This is because you are returning a pointer to an object allocated in automatic memory - an undefined behavior.
If you want to return a string from a function, you need to return either a dynamically-allocated block, or a statically allocated block.
Another choice is to pass the buffer into the function, and provide the length as the return value of the function, in the way the file reading functions do it:
size_t getBitstring(unsigned short int instr, char* buf, size_t buf_size) {
... // Fill in the buffer without going over buf_size
printf("don't get excited yet %s\n", binaryNumber);
return strlen(buf);
}
Here is how you call this function:
char binaryNumber[] = "0000000000000000";
size_t len = getBitstring(instr, binaryNumber, sizeof(binaryNumber));
Now binaryNumber is an automatic variable in the context of the caller, so the memory would be around while the caller needs it.
This is a good example of a problem people hit when they're learning C that they probably wouldn't hit if they were operating in Java or another more modern language that doesn't expose the details of memory layout to the user.
While everyone's answer here is probably technically correct, I'm going to try a different tack to see if I can answer your question without just giving you a line of code that will fix it.
First you need to understand what's going on when returning a
variable defined inside a function, like this:
void f(void) {
int x = 0;
/* do some crazy stuff with x */
return x;
}
What happens when you call return x;? I'm probably omitting some
details here, but what is essentially going on is that the calling
context gets the value stored inside the variable named x at
that time. The storage that is allocated to store that value is
no longer guaranteed to contain that value after the function is
over.
Second, we need to understand what happens when we refer to an array
by its name. Say we have a 'string':
char A[] = "12345";
In C, this is actually equivalent to declaring an array of
characters that ends in a \0:
char A[6] = { '1' , '2' , '3' , '4' , '5' , '\0' };
Then this is sort of like declaring six chars A[0], A[1], ...
, A[5]. The variable A is actually of type char * i.e. it is a
pointer containing the memory address storing A[0] (the beginning
of the array).
Finally, we need to understand what happens when you call printf to
print a string like this:
printf("%s", A);
What you're saying here is "print all the bytes starting at memory
address A until you hit a byte that contains \0".
So, let's put it all together. When you run your code, the variable binaryNumber is a pointer containing the memory address of the first character of the array: binaryNumber[0], and this address is what's returned by the function. BUT, you've declared the array inside of getBitString, so as we know that the memory allocated for the array is no longer guaranteed to store the same values after getBitString is over.
When you run printf("%s", a) you're telling C to "print all the bytes starting at memory address a until you get to a byte containing \0 -- but since that memory address is only guaranteed to contain valid values inside getBitString, what you get is whatever garbage it happens to contain at the time when you call it outside of getBitString.
So what can you do to resolve the problem? Well you have several options, here are is a (non-exhaustive) list:
You declare binaryString outside of getBitString so that it's still valid when you try to access it in main
You declare binaryString as static as some others have suggested, which is effectively the same thing as above, except that the actual variable name binaryString is only valid inside the function, but the memory allocated to store the array is still valid outside the function.
You make a copy of the string using the strdup() function before you return it in your function. Remember that if you do this, you have to free() the pointer returned by strdup() after you're done with it, otherwise what you've got is a memory leak.
Your binaryNumber character array only exists inside of your getBitstring function. Once that function returns, that memory is no longer allocated to your binaryNumber. To keep that memory allocated for use outside of that function you can do one of two things:
Return a dynamically allocated array
char* getBitstring(unsigned short int instr) {
// dynamically allocate array to hold 16 characters (+1 null terminator)
char* binaryNumber = malloc(17 * sizeof(char));
memset(binaryNumber, '0', 16); // Set the first 16 array elements to '0'
binaryNumber[16] = '\0'; // null terminate the string
//....
//doing things to binaryNumber
//.....
return binaryNumber;
}
int main(int argc, char *argv[]) {
char *a = getBitstring(0x1234);
printf("%s", a);
free(a); // Need to free memory, because you dynamically allocated it
return 0;
}
or pass the array into the function as an argument
void* getBitstring(unsigned short int instr, char* binaryNumber, unsigned int arraySize ) {
//....
//doing things to binaryNumber (use arraySize)
//.....
}
int main(int argc, char *argv[]) {
char binaryNumber[] = "0000000000000000";
getBitstring(0x1234, binaryNumber, 16); // You must pass the size of the array
printf("%s", binaryNumber);
return 0;
}
Others have suggested making your binaryNumber array static for a quick fix. This would work, but I would avoid this solution, as it is unnecessary and has other side effects.
Create your return type in dynamic way with malloc() function. create 16+1 blocks for end of string. this is not safe but easy to understand.
char * binaryNumber = (char*) malloc(17*sizeof(char));//create dynamic char sequence
strcpy(binaryNumber,"0000000000000000");//assign the default value with String copy
The final result will be;
char* getBitstring(unsigned short int instr) {
//this is what the code below is going to convert into. It is set to default
//as a 16 bit string full of zeros to act as a safety default.
char * binaryNumber = (char*) malloc(17*sizeof(char));//create dynamic char sequence
strcpy(binaryNumber,"0000000000000000");//assign the default value with String copy function
//....
//doing things to binaryNumber
//.....
printf("don't get excited yet %s\n", binaryNumber); //note, this works
return binaryNumber;
}
int main(int argc, char *argv[]) {
char *a = getBitstring(0x1234);
printf("%s", a); //this fails
return 0;
}
of course include the <string.h> library.
your char binaryNumber[] is local to the function getBitstring(). you cannot return a local variable to other function.
The scope of binaryNumber is over when getBitstring() finishes execution. So, in your main(), char *a is not initialized.
The workaround:
define the array as static so that it does not go out-of-scope. [Not a good approach, but works]
or
use dynamic memory allocation and return the pointer. [don't forget to free later, to avoid memory leak.]
IMO, the second approach is way better.
You need static:
static char binaryNumber[] = "0000000000000000";
Without static keyword, the value of automatic variable is lost after function returns. Probably you know this.

best practice for returning a variable length string in c

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.

Am I passing a copy of my char array, or a pointer?

I've been studying C, and I decided to practice using my knowledge by creating some functions to manipulate strings. I wrote a string reverser function, and a main function that asks for user input, sends it through stringreverse(), and prints the results.
Basically I just want to understand how my function works. When I call it with 'tempstr' as the first param, is that to be understood as the address of the first element in the array? Basically like saying &tempstr[0], right?
I guess answering this question would tell me: Would there be any difference if I assigned a char* pointer to my tempstr array and then sent that to stringreverse() as the first param, versus how I'm doing it now? I want to know whether I'm sending a duplicate of the array tempstr, or a memory address.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* stringreverse(char* tempstr, char* returnptr);
printf("\nEnter a string:\n\t");
char tempstr[1024];
gets(tempstr);
char *revstr = stringreverse(tempstr, revstr); //Assigns revstr the address of the first character of the reversed string.
printf("\nReversed string:\n"
"\t%s\n", revstr);
main();
return 0;
}
char* stringreverse(char* tempstr, char* returnptr)
{
char revstr[1024] = {0};
int i, j = 0;
for (i = strlen(tempstr) - 1; i >= 0; i--, j++)
{
revstr[j] = tempstr[i]; //string reverse algorithm
}
returnptr = &revstr[0];
return returnptr;
}
Thanks for your time. Any other critiques would be helpful . . only a few weeks into programming :P
EDIT: Thanks to all the answers, I figured it out. Here's my solution for anyone wondering:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void stringreverse(char* s);
int main(void)
{
printf("\nEnter a string:\n\t");
char userinput[1024] = {0}; //Need to learn how to use malloc() xD
gets(userinput);
stringreverse(userinput);
printf("\nReversed string:\n"
"\t%s\n", userinput);
main();
return 0;
}
void stringreverse(char* s)
{
int i, j = 0;
char scopy[1024]; //Update to dynamic buffer
strcpy(scopy, s);
for (i = strlen(s) - 1; i >= 0; i--, j++)
{
*(s + j) = scopy[i];
}
}
First, a detail:
int main()
{
char* stringreverse(char* tempstr, char* returnptr);
That prototype should go outside main(), like this:
char* stringreverse(char* tempstr, char* returnptr);
int main()
{
As to your main question: the variable tempstr is a char*, i.e. the address of a character. If you use C's index notation, like tempstr[i], that's essentially the same as *(tempstr + i). The same is true of revstr, except that in that case you're returning the address of a block of memory that's about to be clobbered when the array it points to goes out of scope. You've got the right idea in passing in the address of some memory into which to write the reversed string, but you're not actually copying the data into the memory pointed to by that block. Also, the line:
returnptr = &revstr[0];
Doesn't do what you think. You can't assign a new pointer to returnptr; if you really want to modify returnptr, you'll need to pass in its address, so the parameter would be specified char** returnptr. But don't do that: instead, create a block in your main() that will receive the reversed string, and pass its address in the returnptr parameter. Then, use that block rather than the temporary one you're using now in stringreverse().
Basically I just want to understand how my function works.
One problem you have is that you are using revstr without initializing it or allocating memory for it. This is undefined behavior since you are writing into memory doesn't belong to you. It may appear to work, but in fact what you have is a bug and can produce unexpected results at any time.
When I call it with 'tempstr' as the first param, is that to be understood as the address of the first element in the array? Basically like saying &tempstr[0], right?
Yes. When arrays are passed as arguments to a function, they are treated as regular pointers, pointing to the first element in the array. There is no difference if you assigned &temp[0] to a char* before passing it to stringreverser, because that's what the compiler is doing for you anyway.
The only time you will see a difference between arrays and pointers being passed to functions is in C++ when you start learning about templates and template specialization. But this question is C, so I just thought I'd throw that out there.
When I call it with 'tempstr' as the first param, is that to be understood as the
address of the first element in the array? Basically like saying &tempstr[0],
right?
char tempstr[1024];
tempstr is an array of characters. When passed tempstr to a function, it decays to a pointer pointing to first element of tempstr. So, its basically same as sending &tempstr[0].
Would there be any difference if I assigned a char* pointer to my tempstr array and then sent that to stringreverse() as the first param, versus how I'm doing it now?
No difference. You might do -
char* pointer = tempstr ; // And can pass pointer
char *revstr = stringreverse(tempstr, revstr);
First right side expression's is evaluavated and the return value is assigned to revstr. But what is revstr that is being passed. Program should allocate memory for it.
char revstr[1024] ;
char *retValue = stringreverse(tempstr, revstr) ;
// ^^^^^^ changed to be different.
Now, when passing tempstr and revstr, they decayed to pointers pointing to their respective first indexes. In that case why this would go wrong -
revstr = stringreverse(tempstr, revstr) ;
Just because arrays are not pointers. char* is different from char[]. Hope it helps !
In response to your question about whether the thing passed to the function is an array or a pointer, the relevant part of the C99 standard (6.3.2.1/3) states:
Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.
So yes, other than the introduction of another explicit variable, the following two lines are equivalent:
char x[] = "abc"; fn (x);
char x[] = "abc"; char *px = &(x[0]); fn (px);
As to a critique, I'd like to raise the following.
While legal, I find it incongruous to have function prototypes (such as stringreverse) anywhere other than at file level. In fact, I tend to order my functions so that they're not usually necessary, making one less place where you have to change it, should the arguments or return type need to be changed. That would entail, in this case, placing stringreverse before main.
Don't ever use gets in a real program.. It's unprotectable against buffer overflows. At a minimum, use fgets which can be protected, or use a decent input function such as the one found here.
You cannot create a local variable within stringreverse and pass back the address of it. That's undefined behaviour. Once that function returns, that variable is gone and you're most likely pointing to whatever happens to replace it on the stack the next time you call a function.
There's no need to pass in the revstr variable either. If it were a pointer with backing memory (i.e., had space allocated for it), that would be fine but then there would be no need to return it. In that case you would allocate both in the caller:
char tempstr[1024];
char revstr[1024];
stringreverse (tempstr, revstr); // Note no return value needed
// since you're manipulating revstr directly.
You should also try to avoid magic numbers like 1024. Better to have lines like:
#define BUFFSZ 1024
char tempstr[BUFFSZ];
so that you only need to change it in one place if you ever need a new value (that becomes particularly important if you have lots of 1024 numbers with different meanings - global search and replace will be your enemy in that case rather than your friend).
In order to make you function more adaptable, you may want to consider allowing it to handle any length. You can do that by passing both buffers in, or by using malloc to dynamically allocate a buffer for you, something like:
char *reversestring (char *src) {
char *dst = malloc (strlen (src) + 1);
if (dst != NULL) {
// copy characters in reverse order.
}
return dst;
}
This puts the responsibility for freeing that memory on the caller but that's a well-worn way of doing things.
You should probably use one of the two canonical forms for main:
int main (int argc, char *argv[]);
int main (void);
It's also a particularly bad idea to call main from anywhere. While that may look like a nifty way to get an infinite loop, it almost certainly will end up chewing up your stack space :-)
All in all, this is probably the function I'd initially write. It allows the user to populate their own buffer if they want, or to specify they don't have one, in which case one will be created for them:
char *revstr (char *src, char *dst) {
// Cache size in case compiler not smart enough to do so.
// Then create destination buffer if none provided.
size_t sz = strlen (src);
if (dst == NULL) dst = malloc (sz + 1);
// Assuming buffer available, copy string.
if (dst != NULL) {
// Run dst end to start, null terminator first.
dst += sz; *dst = '\0';
// Copy character by character until null terminator in src.
// We end up with dst set to original correct value.
while (*src != '\0')
*--dst = *src++;
}
// Return reversed string (possibly NULL if malloc failed).
return dst;
}
In your stringreverse() function, you are returning the address of a local variable (revstr). This is undefined behaviour and is very bad. Your program may appear to work right now, but it will suddenly fail sometime in the future for reasons that are not obvious.
You have two general choices:
Have stringreverse() allocate memory for the returned string, and leave it up to the caller to free it.
Have the caller preallocate space for the returned string, and tell stringreverse() where it is and how big it is.

Resources