Using function parameters as both input and output - c

I found myself using function parameters for both input and output and was wondering if what I'm doing is going to bite me later.
In this example buffer_len is such a parameter. It is used by the foo to determine the size of the buffer and tell the caller, main, how much of the buffer has been used up.
#define MAX_BUFFER_LENGTH 16
char buffer[MAX_BUFFER_LENGTH] = {0};
void main(void)
{
uint32_t buffer_len = MAX_BUFFER_LENGTH;
printf("BEFORE: Max buffer length = %u", buffer_len);
foo(buffer, &buffer_len);
printf("BEFORE: Buffer length used = %u", buffer_len);
}
void foo(char *buffer, uint32_t *buffer_len)
{
/* Remember max buffer length */
uint32_t buffer_len_max = *buffer_len;
uint32_t buffer_len_left = buffer_len_max;
/* Add things to the buffer, decreasing the buffer_len_left
in the process */
...
/* Return the length of the buffer used up to the caller */
*buffer_len = buffer_len_max - buffer_len_left;
}
Is this an OK thing to do?
EDIT:
Thank you for your responses, but I'd prefer to keep the return value of foo for the actual function result (which makes sense with larger functions). Would something like this be more pain-free in the long run?
typedef struct
{
char *data_ptr;
uint32_t length_used;
uint32_t length_max;
} buffer_t;
#define ACTUAL_BUFFER_LENGTH 16
char actual_buffer[ACTUAL_BUFFER_LENGTH] = {0};
void main(void)
{
buffer_t my_buffer = { .data_ptr = &actual_buffer[0],
.length_used = 0,
.length_max = ACTUAL_BUFFER_LENGTH };
}

For the original version of the question where the called function doesn't return a value, you got three similar answers, all roughly saying "Yes, but…":
Jonathan Leffler said:
It's "OK" as long as it is documented, but really not the preferred way of operating. Why not have the function return the length used, and leave the buffer length parameter as a regular uint32_t (or perhaps size_t, so you can pass sizeof(buffer) to the function)?
DevSolar said:
It's syntactically OK, but personally I much prefer return codes. If that is not possible, I would want a dedicated output parameter, especially if it's pass-by-reference. (I might not pay attention and continue under the assumption that my buffer_len still holds the original value.)
BeyelerStudios said:
As long as you have not used up your return value, I prefer to receive the result rather than having to defining a variable every time I use the function (or maybe I want to input an expression).
The unanimity is remarkable.
The question was then updated to indicate that instead of returning void, the function's return value would be used for another purpose. This completely changes the assessment.
Don't show a void function if your real function is going to return a value. Doing so completely alters the answers. If you need to return more than one value, then an in-out parameter is OK (even necessary — getchar() is a counter-example), though a pure in parameter and a separate pure out parameter might be better. Using a structure is OK too.
Perhaps I should explain the 'counter-example' a bit. The getchar() function returns a value that indicates failure or a char value. This leads to many pitfalls for beginners (because getchar() returns an int, not a char as its name suggests). It would be better, in some ways, if the function was:
bool get_char(char *c);
returning true if it reads a character and false if it fails, and assigning the character value to c. It could be used like:
char c;
while (get_char(&c))
…use character just read…
This is a case where the function needs to return two values.
Harking back to the suggested revised code in the question, the code using the structure.
That is not a bad idea at all; it is often sensible to package up a set of values into a structure. It would make a lot of sense if the called function has to compute some value that it will return and yet it also modifies the buffer array and needs to report on the number of entries in it (as well as knowing how much space there is to be used). Here, keeping the 'space available' separate from the 'space used' is definitely preferable; it will be easier to see what's going on than having the 'in-out' parameter which informs the function how much space is available on entry and reports back how much space was used on exit. Even if it reported how much space was still available on exit, it would be harder to use.
Which gets back to the original diagnosis: yes, the in-out parameter is technically legal, and can be made to work, but isn't as easy to use as separate values.
Side note: void main(void) is not the standard way to write main() — see What should main() return in C and C++? for the full story.

There's nothing wrong with using the same buffer for input and output, but it probably limits the functions utility elsewhere. For example, what if you want to use it with two different values? (for some reason as a user of the function I need the original preserved). In the example you provide there's no harm in taking two parameters in the function and then just passing the same pointer in twice. Then you've wrapped up both uses and it probably simplifies the function code.
For more complex data types like arrays, as well as the same problem above, you'll need to make sure your function doesn't need a larger output, or if it shrinks the buffer that you memset( 0.. ) the difference and so on.
So for those headaches I do tend to avoid as a pattern, but as I say nothing particularly wrong.

Related

Returning a pointer to a static buffer

In C on a small embedded system, is there any reason not to do this:
const char * filter_something(const char * original, const int max_length)
{
static char buffer[BUFFER_SIZE];
// checking inputs for safety omitted
// copy input to buffer here with appropriate filtering etc
return buffer;
}
this is essentially a utility function the source is FLASH memory which may be corrupted, we do a kind of "safe copy" to make sure we have a null terminated string. I chose to use a static buffer and make it available read only to the caller.
A colleague is telling me that I am somehow not respecting the scope of the buffer by doing this, to me it makes perfect sense for the use case we have.
I really do not see any reason not to do this. Can anyone give me one?
(LATER EDIT)
Many thanks to all who responded. You have generally confirmed my ideas on this, which I am grateful for. I was looking for major reasons not to do this, I don't think that there are any. To clarify a few points:
rentrancy/thread safety is not a concern. It is a small (bare metal) embedded system with a single run loop. This code will not be called from ISRs, ever.
in this system we are not short on memory, but we do want very predictable behavior. For this reason I prefer declaring an object like this statically, even though it might be a little "wasteful". We have already had issues with large objects declared carelessly on the stack, which caused intermittent crashes (now fixed but it took a while to diagnose). So in general, I am preferring static allocation, simply to have very predictability, reliability, and less potential issues downstream.
So basically it's a case of taking a certain approach for a specific system design.
Pro
The behavior is well defined; the static buffer exists for the duration of the program and may be used by the program after filter_something returns.
Cons
Returning a static buffer is prone to error because people writing calls to the routines may neglect or be unaware that a static buffer is returned. This can lead to attempts to use multiple instances of the buffer from multiple calls to the function (in the same thread or different threads). Clear documentation is essential.
The static buffer exists for the duration of the program, so it occupies space at times when it may not be needed.
It really depends on how filter_something is used. Take the following as an example
#include <stdio.h>
#include <string.h>
const char* filter(const char* original, const int max_length)
{
static char buffer[1024];
memset(buffer, 0, sizeof(buffer));
memcpy(buffer, original, max_length);
return buffer;
}
int main()
{
const char *strone, *strtwo;
char deepone[16], deeptwo[16];
/* Case 1 */
printf("%s\n", filter("everybody", 10));
/* Case 2 */
printf("%s %s %s\n", filter("nobody", 7), filter("somebody", 9), filter("anybody", 8));
/* Case 2 */
if (strcmp(filter("same",5), filter("different", 10)) == 0)
printf("Strings same\n");
else
printf("Strings different\n");
/* Case 3 - Both of these end up with the same pointer */
strone = filter("same",5);
strtwo = filter("different", 10);
if (strcmp(strone, strtwo) == 0)
printf("Strings same\n");
else
printf("Strings different\n");
/* Case 4 - You need a deep copy if you wish to compare */
strcpy(deepone, filter("same", 5));
strcpy(deeptwo, filter("different", 10));
if (strcmp(deepone, deeptwo) == 0)
printf("Strings same\n");
else
printf("Strings different\n");
}
The output when gcc is used is
everybody
nobody nobody nobody
Strings same
Strings same
Strings different.
When filter is used by itself, it behaves quite well.
When it is used multiple times in an expression, the behaviour is undefined there is no telling what it will do. All instances will use the contents the last time the filter was executed. This depends on the order in which the execution was performed.
If an instance is taken, the contents of the instance will not stay the same as when the instance was taken. This is also a common problem when C++ coders switch to C# or Java.
If a deep copy of the instance is taken, then the contents of the instance when the instance was taken will be preserved.
In C++, this technique is often used when returning objects with the same consequences.
It is true that the identifier buffer only has scope local to the block in which it is declared. However, because it is declared static, its lifetime is that of the full program.
So returning a pointer to a static variable is valid. In fact, many standard functions do this such as strtok and ctime.
The one thing you need to watch for is that such a function is not reentrant. For example, if you do something like this:
printf("filter 1: %s, filter 2: %s\n",
filter_something("abc", 3), filter_something("xyz", 3));
The two function calls can occur in any order, and both return the same pointer, so you'll get the same result printed twice (i.e. the result of whatever call happens to occur last) instead of two different results.
Also, if such a function is called from two different threads, you end up with a race condition with the threads reading/writing the same place.
Just to add to the previous answers, I think the problem, in a more abstract sense, is to make the filtering result broader in scope than it ought to be. You introduce a 'state' which seems useless, at least if the caller's intention is only to get a filtered string. In this case, it should be the caller who should create the array, likely on the stack, and pass it as a parameter to the filtering method. It is the introduction of this state that makes possible all the problems referred to in the preceding responses.
From a program design, it's frowned upon to return pointers to private data, in case that data was made private for a reason. That being said, it's less bad design to return a pointer to a local static then it is to use spaghetti programming with "globals" (external linkage). Particularly when the pointer returned is const qualified.
One general issue with staticvariables, that may or may not be a problem regardless of embedded or hosted system is re-entrancy. If the code needs to be interrupt/thread safe, then you need to implement means to achieve that.
The obvious alternative to it all is caller allocation and you've got to ask yourself why that's not an option:
void filter_something (size_t size, char dest[size], const char original[size]);
(Or if you will, [restrict size] on both pointers for a mini-optimization.)

Filling a pre-allocated string of fixed size passed as an argument in C

I need to get a fixed length name from a 3rd party developer in a clean way that (hopefully) doesn't require any allocation on their side, and is checked well by the compiler.
I provide a prototype like this:
void getName(char name[9]);
And they would write a function something like this:
void getName(char name[9]) {
strncat(_name, "Hello World", 8);
}
Then I call it (on my side) sort of like this:
char buf[9];
*buf = '\0';
getName(buf);
doSomethingWith(buf);
It compiles and seems to work, but I'm not sure its the best way to handle this.
Any advice?
Edit: To clarify, the name string is used as an identifier in a packed binary save file. It needs to be exactly 8 ASCII 8-bit chars.
I wonder now if I should just receive any string and truncate it on my side. I was hoping the compiler would help instead of this being a runtime check.
In your example, the name is a static string. In this case the function could look like below, where no additional data copy is required:
const char* getName(void)
{
return "Hello World";
}
...
const char* const pName = getName();
Alternatively:
void getName(FUNCPTR func)
{
func("Hello World");
}
where the void func(const char* const pName) is implemented at your side. Then you also don't need to allocate/copy data.
Your first job is to agree the data type of the returned string.
Although it's tempting to use char*, you ought not to since the type of char is not sufficiently well-defined by the standard (could be unsigned, signed 2's complement or signed 1's complement). If you're not careful the behaviour of your program could be undefiend if you mix up your types.
So you ought to decide on a type and use #DEFINE CharType accordingly.
Then as for the function itself, don't rely on the 3rd party to allocate memory unless you call their library to release that memory. Your C runtime might use a different allocation system to theirs. In order to address this common issue, a sort of convention has grown up: if you pass NULL for the output buffer then the 3rd party function should return the length of the buffer required. Then you allocate the memory yourself with the required length, and call the function a second time with the size of the allocated buffer explicitly sent. In that mode, the function returns the length of the allocated string as well as the result populated into the buffer.
Putting this all together, a good prototype would be
SizeType getName(CharType* buffer, SizeType length);
where SizeType is again agreed upon between you and the 3rd party. Broadly speaking, this is how the Windows API works.

Understanding how to turn a chunk of code that appears in main(){} into a function or functions in C

I'm working on a user-space driver which reads data off of a device by sending and receiving reports (it's a hid device).
Here is my initial code http://pastebin.com/ufbvziUR
EDIT NOTE: From the sound of the answers and comments it would seem I will need to wrap my C code inside of some Objective-C since the app that will be consuming this driver is written in Objective-C.
As of now I have just added all the code into the main() function and I'm able to grab data and print it out to the log window with the main purpose of logging out the buffer array. This code will be apart of a much larger app though and will need to be ran by getting called rather than just automatically running.
So I figured I would wrap all the code that appears in main() inside of a large function called getData(). I want to return an array called char buffer[] (a char array full of bytes) when this function get run. My initial thought to declare it would be like so since I know you cannot really return an array from a function only a pointer so I just let the caller allocate the buffer and pass it the size.
char *getData(int user){
unsigned char *buffer = malloc(2800);
// ... do all the stuff
return buffer;
}
Then in main()
int main(){
int user = 1;
unsigned char *buffer = getData(user);
}
Is this a proper approach?
A couple of things feel wrong to me here. First is wrapping that much code into a single function and two I'm not quite sure how to break out of the function when one of my error checks returns 1; since this function will need to return an array. I'm still really new to C and am getting confused on how to approach this when I don't have objects or classes to work with.
void getData(unsigned char *buffer, int user){...}
Defines a function that is not returning anything.
If you want to return some value - like for instance error code, you need a function returning an int.
int getData(unsigned char *buffer, int user){...}
To get out of function returning void differently then reaching the end of the function, you can also use return but then without any arguments.
As you've already noticed you aren't passing array to the function so there is no reason to return it at all. You could return the pointer if you wanted but the is no need to do so. The main function knows where the array is anyway.
It's generally considered a good habit to keep main as short as possible. You can also divide getData into smaller functions which would make the code more readable. You could for instance make every chunk marked by # pragma mark - ... a separate function. Or even better, see whether there are any parts of the program that are doing the same or similar thing. Then you can generalize this functionality into one function and use it multiple times.

Getting return value from a function in C

consider the the two functions :
int add1(int x,int y)
{
return x+y;
}
void add2(int x,int y,int *sum)
{
*sum=x+y;
}
I generally use functions of the form add1 but I found some codes using functions of the form add2.
Even if the size return value is large(like an array or struct) we can just return its ponter
I wonder if there any reason for using the second form?
There's also the reason of returning success state.
There are a lot of functions like:
bool f(int arg1, int arg2, int *ret)
{
}
Where bool (or enum) return the success of the function. Instead of checking if ret is null... (And if you had more than 1 variable).
If you want to return two values from your function, then C is helpless unless you use pointers just like your function add2.
void add2()
{
/* Some Code */
*ptr1=Something;
*ptr2=Something;
}
Form 2 is very common for "multiple returns" in C. A canonical example is returning the address to a buffer and the length of the buffer:
/* Returns a buffer based on param. Returns -1 on failure, or 0 on success.
Buffer is returned in buf and buflen. */
int get_buffer(void *param, char **buf, int *buflen);
Functions of the form 2 are not faster than functions of the form 1 when you're using things as small as int. In fact, in this case, the second one is slower because you have to dereference the passed pointer. It's only useful in this case if your aim was to pass in an array of values)
Always use functions of the form 1 unless you want to pass in a very large piece of data to the function. In that case, the form 2 would be faster.
The reason we use the second form is because for large objects, we want to avoid copying them. Instead of copying them, we could just pass their memory addresses to the function. This is where the pointer comes in. So instead of giving the function all the data, you would just tell it where this data. (I hope this analogy is good enough)
It is largely a matter of preference and local conventions. The second form might be used alongside a bunch of other similar functions where the third parameter in each of them is always passed as a pointer to a return value.
Personally, I like the first form for almost all purposes: it does not require a pointer to be passed, and it allows some type flexibility in handling the return value.
Returning a value by writing to memory passed via a pointer is reasonable, when the returned object is large, or when the return value of the function is used for other purposes (e.g. signaling error conditions). In the code you have shown, neither of these two is the case, so I'd go for the first implementation.
When you return a pointer from a function, you have to make sure that the pointed to memory is valid after the function call. This means, the pointer must point to the heap, making an allocation on the heap necessary. This puts a burdon on the caller; he has to deallocate memory that he did not explicitly allocate.

In C, what is a safer function to use than strtrns?

strtrns has the following descriptions: desc-1, desc-2
The strtrns() function transforms string and copies it into
result.
Any character that appears in old is replaced with the character in
the same position in new. The new result is returned. .........
This function is a security risk because it is possible to overflow
the newString buffer. If the currentString buffer is larger than the
newString buffer, then an overflow will occur.
And this is its prototype( or "signature"? ":
char * strtrns(const char *string, const char *old, const char *new, char *result);
I've been googling to no avail. I appreciate any tips or advice.
I think you can write your own safe one pretty quickly.
It won't be a direct replacement, as the signature is slightly different, and it will allocate memory that the caller must free, but it can serve mostly the same job.
(I'm also changing the parameter name new, which is a reserved word in C++, and the parameter string which is a very common type in C++. These changes makes the function compatible with C++ code as well)
char* alloc_strtrns(const char *srcstr, const char *oldtxt, const char *newtxt)
{
if (strlen(oldtxt) != strlen(newtxt))
{
return NULL; /* Old and New lengths MUST match */
}
char* result = strdup(srcstr); /* TODO: check for NULL */
/* Caller is responsible for freeing! */
return strtrns(srcstr, oldtxt, newtxt, result);
}
The claim that this function is unsafe is nonsense. In C, whenever you have an interface that takes a pointer to a buffer and fills it with some amount of data, you must have a contract between the caller and callee regarding the buffer size. For some functions where the caller cannot know in advance how much data the callee will write, the most logical interface design (contract) is to have the caller pass the buffer size to the callee and have the callee return an error or truncate the data if the buffer is too small. But for functions like strcpy or in your case strtrns where the number of output bytes is a trivial function (like the identity function) of the number of input bytes, it makes perfectly good sense for the contract to simply be that the output buffer provided by the caller must be at least as large as the input buffer.
Anyone who is not comfortable with strict adherence to interface contracts should not be writing C. There is really no way around this; adding complex bounds-checking interfaces certainly does not solve the problem but just shifts around the nature of the contracts you have to follow.
By the way, strtrns is not a standard function anyway so if you'd prefer a different contract anyway you might be better off writing your own similar function. This would increase portability too.
You don't really have any options in C. You simply have to ensure that the destination buffer is large enough.

Resources