I am programming in C against a third party library (in HP/Mercury Loadrunner) that allows a varargs-style variable size argument list for one of it's functions. I want to call this function but I do not know up front how many arguments I will have.
There is a function made by one of my predecessors that serves somewhat but the problem here is that this function assumes the worst case scenario (over 3000 arguments) and hand-codes for that.
To illuminate, here's the (beginning of) the code. The function we call is web_submit_data(). It will HTTP post a set of form data. This implementation came about when dealing with dynamically generated forms with an arbitrary number of fields.
(Cleaned up a fair bit from the original, which hand coded indexes by hand as well..)
web_submit_data_buffer_gazillion_items( const char *bufferName, const char *bufferValue)
{
const int size = 129;
int i = 0;
int j = 11;
web_submit_data(&bufferName[i++ * size], //"some form"
&bufferName[i++ * size], //"Action=https://blah.blah/form");
&bufferName[i++ * size], //"Method=POST");
&bufferName[i++ * size], //"TargetFrame=");
&bufferName[i++ * size], //"RecContentType=text/html");
&bufferName[i++ * size], //"Referer=https://blah.blah/index.html");
&bufferName[i++ * size], //"Snapshot=t1.inf");
&bufferName[i++ * size], //"Mode=HTML");
ITEMDATA, // missing in action: indexes 8 through 10
&bufferName[j * size],&bufferValue[j++ * size], ENDITEM,
&bufferName[j * size],&bufferValue[j++ * size], ENDITEM,
&bufferName[j * size],&bufferValue[j++ * size], ENDITEM,
..
(repeat the last 3 lines ad nauseum)
..
&bufferName[j * size],&bufferValue[j++ * size], ENDITEM,
&bufferName[j * size]);
}
Now I have found an external library that might work (http://www.dyncall.org) but I would much rather not a) be completely processor dependant and b) attempt to teach Loadrunner about linking in external sources..
Edit:
The original function used hardcoded indexes instead of using a variable. Can still revert to that if it turns out to be too unpredictable. However, as I am unlikely to run this with a different compiler or hardware / OS I doubt that really is worth it.
Also: I don't have control over the implementation of web_submit_data(). So just pushing the problem down one level isn't going to cut it..
Another thing to note: The spec for web_submit_data() uses a constant called LAST to mark the end of the argument list. The original implementation doesn't use it. Presumably the callsite does ..
In CamelBones I use libffi to call objc_msgSend(), which is a varargs function. Works a treat.
Variable length arguments are basically just a pointer to a bunch of packed data that is passed to the required function. It is the responsibility of the called function to interpret this packed data.
The architecture safe way to do this is to use the va_list macros (that n-alexander mentioned), otherwise you may run into issues with how various data types are padded in memory.
The proper way to design varargs functions is to actually have two versions, one that accepts the '...', which in turn extracts the va_list and passes it to a function that takes a va_list. This way you can dynamically construct the arguments if you need to and can instead call the va_list version of the function.
Most standard IO functions have varargs versions: vprintf for printf, vsprintf for sprintf... you get the idea. See if your library implements a function named "vweb_submit_data" or something to that effect. If they don't, email them and tell them to fix their library.
3000 lines of the same thing (even if it is preprocessor induced) makes me cringe
Since it's generally not a problem to pass more arguments to a function taking variable arguments than the function expects (see footnote #1), you can do something like the following:
// you didn't give a clear specification of what you want/need, so this
// example may not be quite what you want as I've had to guess at
// some of the specifications. Hopefully the comments will make clear
// what I may have assumed.
//
// NOTE: while I have compiled this example, I have not tested it,
// so there is a distinct possiblity of bugs (particularly
// off-by-one errors). Check me on this stuff, please.
// I made these up so I could compile the example
#define ITEMDATA ((char const*) NULL)
#define ENDITEM ((char const*) 0xffffffff)
void web_submit_data_wrapper( const char*bufferName,
const char* bufferValue,
size_t headerCount, // number of header pointers to pass (8 in your example)
size_t itemStartIndex, // index where items start in the buffers (11 in your example)
size_t itemCount, // number of items to pass (unspecified in your example)
size_t dataSize ) // size of each header or item (129 in your example)
{
// kMaxVarArgs would be 3000 or a gazillion in your case
// size_t const kMaxVarArgs = 20; // I'd prefer to use this in C++
#define kMaxVarArgs (20)
typedef char const* char_ptr_t;
typedef char_ptr_t char_ptr_array_t[kMaxVarArgs];
char_ptr_array_t varargs = {0};
size_t idx = 0;
// build up the array of pararmeters we'll pass to the variable arg list
// first the headers
while (headerCount--) {
varargs[idx++] = &bufferName[idx * dataSize];
}
// mark the end of the header data
varargs[idx++] = ITEMDATA;
// now the "items"
while (itemCount--) {
varargs[idx++] = &bufferName[itemStartIndex * dataSize];
varargs[idx++] = &bufferValue[itemStartIndex * dataSize];
varargs[idx++] = ENDITEM;
++itemStartIndex;
}
// the thing after the last item
// (I'm not sure what this is from your example)
varargs[idx] = &bufferName[itemStartIndex * dataSize];
// now call the target function - the fact that we're passing more arguments
// than necessary should not matter due to the way VA_ARGS are handled
// but see the Footnote in the SO answer for a disclaimer
web_submit_data(
varargs[0],
varargs[1],
varargs[2],
//... ad nasuem until
varargs[kMaxVarArgs-1]
);
}
Footnote #1: If you think about how the macros in stdargs.h act this becomes clear. However, I do not claim that this technique would be standards compliant. In fact, in recent history the stackoverflow answers I've posted where I;ve made this disclaimer have in fact been found to be non-standards compliant (usually by the ever vigilant litb). So use this technique at your own risk, and verify, verify, verify).
There is no portable way to build up an argument list for a variable argument function in C at run time. There are a few implementation-dependent tricks out there, the dyncall library you found looks like a good one and probably more portable than most.
Note: the code is already compiler-dependent (though perhaps not processor-dependent), because the invocation of web_submit_data assumes there that the argument subexpressions in a procedure call are evaluated from left-to-right order, but the C language leaves the order of argument evaluation unspecified.
See for reference: http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value
So perhaps the non-portable solution is not going to make things significantly worse for you.
Can you restructure your code so that this isn't necessary? Perhaps you could take the incoming buffer and make it more deterministic:
struct form_field
{
char[FIELD_NAME_MAX] name;
char[FIELD_VALUE_MAX] val;
};
web_submit_data_buffer_gazillion_items( const char *bufferName, const char *bufferValue)
{
/*
loop over bufferName somehow, either with a known size or terminating record,
and build an array of form_field records
*/
//loop
{
// build array of records
}
web_submit_data(record_array, array_len);
}
Sorry this couldn't be more fleshed out - my wife called me in for breakfast. :-)
Write it once with the preprocessor and never look back.
#define WEB_SUBMIT_BUFFER(name, val) \
do { \
const int size = 129; \
int i = 0; \
int j = 11; \
web_submit_data(&(name)[i++ * size], \
&(name)[i++ * size], \
/* etc ad nauseum */ \
} while (0)
Or if the number of arguments is fixed for each specific call, write a script to generate preprocessor defines to hide how heinous that call is.
#define WEB_SUBMIT_BUFFER_32(name, val) \
do { \
const int size = 129; \
int i = 0; \
int j = 11; \
web_submit_data(&(name)[i++ * size], \
&(name)[i++ * size], \
/* 32 times */ \
} while (0)
#define WEB_SUBMIT_BUFFER_33(name, val) ...
#define WEB_SUBMIT_BUFFER_34(name, val) /* etc */
Note that the code sample you posted has undefined behavior - the commas that separate function parameters are not sequence points (those commas are not the comma operator), so modifying i and or j multiple times in the function call argument list results in undefined behavior.
This is not to mention that the evaluation order of function call arguments is not specified by the standard - so even if you did the modification of i and j using functions to evaluate the arguments (function calls themselves are sequence points), you would be pretty much passing the pointers in an indeterminate order.
Also, I don't see how web_submit_data() knows how many arguments it's been passed - I don't see a count or a definitive sentinel argument at the end. But I guess your example may be just that - an example that might not have complete, accurate details. On the other hand, it's web_submit_data()'s problem anyway, right?
There are two way to pass a variable number of arguments: to a function that accepts "..." or to a function that accepts va_list.
You can not dynamically define the number of arguments for the "..." interface, but you should be able to do so for the va_list one. Google for va_start, va_end, and va_list.
I know this is an old thread, but I just ran across it. The proper way to handle variable length submit form data in LoadRunner is to use a web_custom_request(). You build the name|value pair structure for the variable length of the arguments as a string and pass it in as a part of the function.
Record the one call as a web_custom_request() and the structure of the argument string for the name|value pairs will become obvious. Simply use any C string handling functions you wish to construct the string in question and include it as a part of the argument list for the web_custom_request().
Related
I am programming in C against a third party library (in HP/Mercury Loadrunner) that allows a varargs-style variable size argument list for one of it's functions. I want to call this function but I do not know up front how many arguments I will have.
There is a function made by one of my predecessors that serves somewhat but the problem here is that this function assumes the worst case scenario (over 3000 arguments) and hand-codes for that.
To illuminate, here's the (beginning of) the code. The function we call is web_submit_data(). It will HTTP post a set of form data. This implementation came about when dealing with dynamically generated forms with an arbitrary number of fields.
(Cleaned up a fair bit from the original, which hand coded indexes by hand as well..)
web_submit_data_buffer_gazillion_items( const char *bufferName, const char *bufferValue)
{
const int size = 129;
int i = 0;
int j = 11;
web_submit_data(&bufferName[i++ * size], //"some form"
&bufferName[i++ * size], //"Action=https://blah.blah/form");
&bufferName[i++ * size], //"Method=POST");
&bufferName[i++ * size], //"TargetFrame=");
&bufferName[i++ * size], //"RecContentType=text/html");
&bufferName[i++ * size], //"Referer=https://blah.blah/index.html");
&bufferName[i++ * size], //"Snapshot=t1.inf");
&bufferName[i++ * size], //"Mode=HTML");
ITEMDATA, // missing in action: indexes 8 through 10
&bufferName[j * size],&bufferValue[j++ * size], ENDITEM,
&bufferName[j * size],&bufferValue[j++ * size], ENDITEM,
&bufferName[j * size],&bufferValue[j++ * size], ENDITEM,
..
(repeat the last 3 lines ad nauseum)
..
&bufferName[j * size],&bufferValue[j++ * size], ENDITEM,
&bufferName[j * size]);
}
Now I have found an external library that might work (http://www.dyncall.org) but I would much rather not a) be completely processor dependant and b) attempt to teach Loadrunner about linking in external sources..
Edit:
The original function used hardcoded indexes instead of using a variable. Can still revert to that if it turns out to be too unpredictable. However, as I am unlikely to run this with a different compiler or hardware / OS I doubt that really is worth it.
Also: I don't have control over the implementation of web_submit_data(). So just pushing the problem down one level isn't going to cut it..
Another thing to note: The spec for web_submit_data() uses a constant called LAST to mark the end of the argument list. The original implementation doesn't use it. Presumably the callsite does ..
In CamelBones I use libffi to call objc_msgSend(), which is a varargs function. Works a treat.
Variable length arguments are basically just a pointer to a bunch of packed data that is passed to the required function. It is the responsibility of the called function to interpret this packed data.
The architecture safe way to do this is to use the va_list macros (that n-alexander mentioned), otherwise you may run into issues with how various data types are padded in memory.
The proper way to design varargs functions is to actually have two versions, one that accepts the '...', which in turn extracts the va_list and passes it to a function that takes a va_list. This way you can dynamically construct the arguments if you need to and can instead call the va_list version of the function.
Most standard IO functions have varargs versions: vprintf for printf, vsprintf for sprintf... you get the idea. See if your library implements a function named "vweb_submit_data" or something to that effect. If they don't, email them and tell them to fix their library.
3000 lines of the same thing (even if it is preprocessor induced) makes me cringe
Since it's generally not a problem to pass more arguments to a function taking variable arguments than the function expects (see footnote #1), you can do something like the following:
// you didn't give a clear specification of what you want/need, so this
// example may not be quite what you want as I've had to guess at
// some of the specifications. Hopefully the comments will make clear
// what I may have assumed.
//
// NOTE: while I have compiled this example, I have not tested it,
// so there is a distinct possiblity of bugs (particularly
// off-by-one errors). Check me on this stuff, please.
// I made these up so I could compile the example
#define ITEMDATA ((char const*) NULL)
#define ENDITEM ((char const*) 0xffffffff)
void web_submit_data_wrapper( const char*bufferName,
const char* bufferValue,
size_t headerCount, // number of header pointers to pass (8 in your example)
size_t itemStartIndex, // index where items start in the buffers (11 in your example)
size_t itemCount, // number of items to pass (unspecified in your example)
size_t dataSize ) // size of each header or item (129 in your example)
{
// kMaxVarArgs would be 3000 or a gazillion in your case
// size_t const kMaxVarArgs = 20; // I'd prefer to use this in C++
#define kMaxVarArgs (20)
typedef char const* char_ptr_t;
typedef char_ptr_t char_ptr_array_t[kMaxVarArgs];
char_ptr_array_t varargs = {0};
size_t idx = 0;
// build up the array of pararmeters we'll pass to the variable arg list
// first the headers
while (headerCount--) {
varargs[idx++] = &bufferName[idx * dataSize];
}
// mark the end of the header data
varargs[idx++] = ITEMDATA;
// now the "items"
while (itemCount--) {
varargs[idx++] = &bufferName[itemStartIndex * dataSize];
varargs[idx++] = &bufferValue[itemStartIndex * dataSize];
varargs[idx++] = ENDITEM;
++itemStartIndex;
}
// the thing after the last item
// (I'm not sure what this is from your example)
varargs[idx] = &bufferName[itemStartIndex * dataSize];
// now call the target function - the fact that we're passing more arguments
// than necessary should not matter due to the way VA_ARGS are handled
// but see the Footnote in the SO answer for a disclaimer
web_submit_data(
varargs[0],
varargs[1],
varargs[2],
//... ad nasuem until
varargs[kMaxVarArgs-1]
);
}
Footnote #1: If you think about how the macros in stdargs.h act this becomes clear. However, I do not claim that this technique would be standards compliant. In fact, in recent history the stackoverflow answers I've posted where I;ve made this disclaimer have in fact been found to be non-standards compliant (usually by the ever vigilant litb). So use this technique at your own risk, and verify, verify, verify).
There is no portable way to build up an argument list for a variable argument function in C at run time. There are a few implementation-dependent tricks out there, the dyncall library you found looks like a good one and probably more portable than most.
Note: the code is already compiler-dependent (though perhaps not processor-dependent), because the invocation of web_submit_data assumes there that the argument subexpressions in a procedure call are evaluated from left-to-right order, but the C language leaves the order of argument evaluation unspecified.
See for reference: http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value
So perhaps the non-portable solution is not going to make things significantly worse for you.
Can you restructure your code so that this isn't necessary? Perhaps you could take the incoming buffer and make it more deterministic:
struct form_field
{
char[FIELD_NAME_MAX] name;
char[FIELD_VALUE_MAX] val;
};
web_submit_data_buffer_gazillion_items( const char *bufferName, const char *bufferValue)
{
/*
loop over bufferName somehow, either with a known size or terminating record,
and build an array of form_field records
*/
//loop
{
// build array of records
}
web_submit_data(record_array, array_len);
}
Sorry this couldn't be more fleshed out - my wife called me in for breakfast. :-)
Write it once with the preprocessor and never look back.
#define WEB_SUBMIT_BUFFER(name, val) \
do { \
const int size = 129; \
int i = 0; \
int j = 11; \
web_submit_data(&(name)[i++ * size], \
&(name)[i++ * size], \
/* etc ad nauseum */ \
} while (0)
Or if the number of arguments is fixed for each specific call, write a script to generate preprocessor defines to hide how heinous that call is.
#define WEB_SUBMIT_BUFFER_32(name, val) \
do { \
const int size = 129; \
int i = 0; \
int j = 11; \
web_submit_data(&(name)[i++ * size], \
&(name)[i++ * size], \
/* 32 times */ \
} while (0)
#define WEB_SUBMIT_BUFFER_33(name, val) ...
#define WEB_SUBMIT_BUFFER_34(name, val) /* etc */
Note that the code sample you posted has undefined behavior - the commas that separate function parameters are not sequence points (those commas are not the comma operator), so modifying i and or j multiple times in the function call argument list results in undefined behavior.
This is not to mention that the evaluation order of function call arguments is not specified by the standard - so even if you did the modification of i and j using functions to evaluate the arguments (function calls themselves are sequence points), you would be pretty much passing the pointers in an indeterminate order.
Also, I don't see how web_submit_data() knows how many arguments it's been passed - I don't see a count or a definitive sentinel argument at the end. But I guess your example may be just that - an example that might not have complete, accurate details. On the other hand, it's web_submit_data()'s problem anyway, right?
There are two way to pass a variable number of arguments: to a function that accepts "..." or to a function that accepts va_list.
You can not dynamically define the number of arguments for the "..." interface, but you should be able to do so for the va_list one. Google for va_start, va_end, and va_list.
I know this is an old thread, but I just ran across it. The proper way to handle variable length submit form data in LoadRunner is to use a web_custom_request(). You build the name|value pair structure for the variable length of the arguments as a string and pass it in as a part of the function.
Record the one call as a web_custom_request() and the structure of the argument string for the name|value pairs will become obvious. Simply use any C string handling functions you wish to construct the string in question and include it as a part of the argument list for the web_custom_request().
Question
I try to find static (compile time) asserts, to ensure (as good as possible) things below. As I use them in an auto code generation context (see “Background” below) they do not have to be neat, the only have to break compilation, at best with zero overhead. Elegant variants are welcomed though.
The following things shall be checked:
A Type Identity
typedef T T1;
typedef T T2;
typedef X T3;
T1 a;
T2 b;
T3 c;
SA_M1(T1,T2); /* compilation */
SA_M1(T1,T3); /* compilation error */
SA_M2(a,b); /* compilation */
SA_M2(a,c); /* compilation error */
where X and T are C Types (including structured, aggregated, object pointer, not so important function pointer). Note again, that a set of partly successful solutions also helps.
Some solutions that I assume will partly work:
comparing the sizes
checking if the type is a pointer as claimed by trying to dereference it.
for unsigned integers: Compare a casted slightly to big value with the expected wrap around value.
for floats, compare double precision exact representable value with the casted one (hoping the best for platform specific rounding operations)
B A Variable has global Scope
My solution here is at the momement simply to generate a static function, that tries to get a reference to the global variable Assume that X is a global variable:
static void SA_IsGlobal_X() {(void) (&X == NULL); /* Dummy Operation */}
C A Function has the correct number of parameters
I have no idea yet.
D If the prototype of a functions is as it is expected
I have no idea yet.
E If a function or macro parameters are compile time constants (
This question is discussed here for macros:
Macro for use in expression while enforcing its arguments to be compile time constants
For functions, an wrapper macro could do.
Z Other things you might like to check considering the “background” part below
Preferred are answers that can be done with C89, have zero costs in runtime, stack and (with most compilers) code size. As the checks will be auto generated, readability is not so important, but I like to place the checks in static functions, whenever possible.
Background:
I want to provide C functions as well as an interface generator to allow them to smoothly being integrated in different C frameworks (with C++ on the horizon). The user of the interface generator then only specifies where the inputs come from, and which of the outputs shall go where. Options are at least:
RAW (as it is implemented - and should be used)
from the interface functions parameter, which is of a type said to be the same as my input/output (and perhaps is a field of a structure or an array element)
from a getter/setter function
from a global variable
using a compile time constant
I will:
ask for a very detailed interface specification (including specification errors)
use parsers to check typedefs and declarations (including tool bugs and my tool usage errors)
But this happens at generation time. Besides everything else: if the user change either the environment or takes a new major version of my function (this can be solved by macros checking versions), without running the interface generator again, I would like to have a last defense line at compile time.
The resulting code of the generations might near worst case be something like:
#include "IFMyFunc.h" /* contains all user headers for the target framework(s) */
#include "MyFunc.h"
RetType IFMYFunc(const T1 a, const struct T2 * const s, T3 * const c)
{
/* CHECK INTERFACE */
CheckIFMyFunc();
/* get d over a worst case parametrized getter function */
const MyD_type d = getD(s->dInfo);
/* do horrible call by value and reference stuff, f and g are global vars */
c.c1 = MyFunc(a,s->b,c.c1,d,f,&(c->c2), &e,&g);
set(e);
/* return something by return value */
return e;
}
(I am pretty sure I will restrict the combos though).
static void CheckIFMyFunc(void)
{
/* many many compile time checks of types and specifications */
}
or I will provide a piece of code (local block) to be directly infused - which is horrible architecture, but might be necessary if we can't abandon some of the frame work fast enough, supported by some legacy scripts.
for A, would propose:
#define SA_M1(A, B) \
do { \
A ___a; \
B ___b = ___a; \
(void)___b; \
} while (0)
for D (and I would say that C is already done by D)
typedef int (*myproto)(int a, char **c);
#define FN_SA(Ref, Challenger) \
do { \
Ref ___f = Challenger; \
(void) ___f; \
} while (0)
void test(int argc, char **argv);
int main(int argc, char **argv)
{
FN_SA(myproto, main);
FN_SA(myproto, test); /* Does not compile */
return 0;
}
Nevertheless, there are some remaining problems with void *:
any pointer may be casted to/from void * in C, which will probably make the solution for A fail in some cases....
BTW, if you plan to use C++ in the meanterm, you could just use C++ templates and so on to have this stests done here. Would be far more clean and reliable IMHO.
I am a programmer who knows both C and C++. I have used both languages in my own projects but I do not know which one I prefer.
When I program in C the feature that I miss the most from C++ is std::vector from the STL (Standard Template Library)
I still haven't figured out how I should represent growing arrays in C. Up to this point I duplicated my memory allocation code all over the place in my projects. I do not like code duplication and I know that it is bad practice so this does not seems like a very good solution to me.
I thought about this problem some time ago and came up with the idea to implement a generic vector using preprocessor macros.
This is how the implementation looks:
#ifndef VECTOR_H_
#define VECTOR_H_
#include <stdlib.h>
#include <stdio.h>
/* Declare a vector of type `TYPE`. */
#define VECTOR_OF(TYPE) struct { \
TYPE *data; \
size_t size; \
size_t capacity; \
}
/* Initialize `VEC` with `N` capacity. */
#define VECTOR_INIT_CAPACITY(VEC, N) do { \
(VEC).data = malloc((N) * sizeof(*(VEC).data)); \
if (!(VEC).data) { \
fputs("malloc failed!\n", stderr); \
abort(); \
} \
(VEC).size = 0; \
(VEC).capacity = (N); \
} while (0)
/* Initialize `VEC` with zero elements. */
#define VECTOR_INIT(VEC) VECTOR_INIT_CAPACITY(VEC, 1)
/* Get the amount of elements in `VEC`. */
#define VECTOR_SIZE(VEC) (VEC).size
/* Get the amount of elements that are allocated for `VEC`. */
#define VECTOR_CAPACITY(VEC) (VEC).capacity
/* Test if `VEC` is empty. */
#define VECTOR_EMPTY(VEC) ((VEC).size == 0)
/* Push `VAL` at the back of the vector. This function will reallocate the buffer if
necessary. */
#define VECTOR_PUSH_BACK(VEC, VAL) do { \
if ((VEC).size + 1 > (VEC).capacity) { \
size_t n = (VEC).capacity * 2; \
void *p = realloc((VEC).data, n * sizeof(*(VEC).data)); \
if (!p) { \
fputs("realloc failed!\n", stderr); \
abort(); \
} \
(VEC).data = p; \
(VEC).capacity = n; \
} \
(VEC).data[VECTOR_SIZE(VEC)] = (VAL); \
(VEC).size += 1; \
} while (0)
/* Get the value of `VEC` at `INDEX`. */
#define VECTOR_AT(VEC, INDEX) (VEC).data[INDEX]
/* Get the value at the front of `VEC`. */
#define VECTOR_FRONT(VEC) (VEC).data[0]
/* Get the value at the back of `VEC`. */
#define VECTOR_BACK(VEC) (VEC).data[VECTOR_SIZE(VEC) - 1]
#define VECTOR_FREE(VEC) do { \
(VEC).size = 0; \
(VEC).capacity = 0; \
free((VEC).data); \
} while(0)
#endif /* !defined VECTOR_H_ */
This code goes in the header file called "vector.h".
Note that it does miss some functionality (like VECTOR_INSERT and VECTOR_ERASE) but I think that it is good enough to show my concept.
The use of the vector looks like this:
int main()
{
VECTOR_OF(int) int_vec;
VECTOR_OF(double) dbl_vec;
int i;
VECTOR_INIT(int_vec);
VECTOR_INIT(dbl_vec);
for (i = 0; i < 100000000; ++i) {
VECTOR_PUSH_BACK(int_vec, i);
VECTOR_PUSH_BACK(dbl_vec, i);
}
for (i = 0; i < 100; ++i) {
printf("int_vec[%d] = %d\n", i, VECTOR_AT(int_vec, i));
printf("dbl_vec[%d] = %f\n", i, VECTOR_AT(dbl_vec, i));
}
VECTOR_FREE(int_vec);
VECTOR_FREE(dbl_vec);
return 0;
}
It uses the same allocation rules as std::vector (the size starts as 1 and then doubles each time that is required).
To my surprise I found out that this code runs more than twice as fast as the same code written using std::vector and generates a smaller executable! (compiled with GCC and G++ using -O3 in both cases).
My questions to you are:
Are there any serious faults with this approach?
Would you recommend using this in a serious project?
If not then I would like you to explain why and tell me what a better alternative would be.
To my surprise I found out that this code runs more than twice as fast as the same code written using std::vector and generates a smaller executable! (compiled with GCC and G++ using -O3 in both cases).
There are three reasons why your C version is faster/smaller than the C++ version:
The implementation of new in the standard C++ library that is used by g++ is suboptimal. If you implement void* operator new (size_t size) as a call-through to malloc() you get better performance than with the built-in version.
If realloc() has to use a new chunk of memory, it moves the old data over in the fashion of memmove(), i. e. it ignores the logical structure of the data and simply moves the bits. That operation can easily be accelerated to the point that the memory bus is the bottleneck. std::vector<>, on the other hand, must take care of possibly calling constructors/destructors correctly, it can't just call through to memmove(). In the case of int and double that boils down to moving the data one int/double at a time, the loop is in the code generated for the std::vector<>. That is not too bad, but its worse than using SSE instructions which a good memmove() implementation will do.
The realloc() function is part of the standard C library which is dynamically linked to your executable. The memory management code generated by std::vector<>, however, is precisely that: generated. As such, it must be a part of your executable.
Are there any serious faults with this approach?
This is a matter of taste, but I think, the approach is smelly: Your macro definitions are far away from their uses, and they do not all behave like simple constants or inline function. In fact, they act suspiciously like elements of a programming language (i. e. templates), which is not a good thing for preprocessor macros. It is generally a bad idea to try to modify the language by use of the preprocessor.
You also have a serious issue with your macro implementations: The VECTOR_INIT_CAPACITY(VEC, N) macro evaluates its VEC argument four times and the N argument twice. Now think about what happens if you do a call VECTOR_INIT_CAPACITY(foo, baz++): The size stored in the capacity field of the new vector will be larger than the size of the memory allocated for it. The line with the malloc() call will increment the baz variable, and that new value will be stored in the capacity member before baz is incremented a second time. You should write all macros in a way that the evaluate their arguments exactly once.
Would you recommend using this in a serious project?
I think, I wouldn't bother. The realloc() code is trivial enough that some replications won't hurt too much. But again, your mileage may vary.
If not then I would like you to explain why and tell me what a better alternative would be.
As I said before, I wouldn't bother trying to write a general container class in the style of std::vector<>, neither by (ab)using the preprocessor, nor by (ab)using void*.
But I would take a close look at the memory handling on the system that I write for: With many kernels, it is extremely unlikely that you ever get a return value of NULL out of a malloc()/realloc() call. They over-commit their memory, making promises they cannot be certain to be able to fulfill. And when they realize that they can't back up their promises, they start shooting processes via the OOM-killer. On such a system (linux is one of them), your error handling is simply pointless. It will never get executed. As such, you can avoid the pain of adding it and replicating it to all the places where you need a dynamically growing array.
My memory reallocation code in C usually looks something like this:
if(size == capacity) {
array = realloc(array, (capacity *= 2) * sizeof(*array));
}
array[size++] = ...;
Without the functionless error handling code, this is so short that it can safely be replicated as many times as it is needed.
Are there any serious faults with this approach?
You're reinventing templates in a way that interacts poorly with C's type system. For instance, your VECTOR types are anonymous, so I can't write a function that takes a VECTOR_OF(int) as a parameter.
Even if you do name your types somehow, I wouldn't be able to write a generic function---something that takes a VECTOR_OF(T) for arbitrary T and does something with it.
These might not be serious faults, but there's a hundred minor drawbacks like this to every generics-using-macros approach I've seen in C. This all comes up because the language doesn't try to support generic programming at all.
Would you recommend using this in a serious project?
Sure; you can develop a serious project using container types like this, and they won't even necessarily get in your face. You'll probably need to traffic in void *'s to pass these things around, and that leads to some casting that's a little bit error-prone.
My questions to you are:
Are there any serious faults with this approach?
Yes, you're trying to reinvent the wheel.
Would you recommend using this in a serious project?
No, especially since your speed up generally indicated you might be missing some security checks.
If not then I would like you to explain why and tell me what a better alternative would be.
VPool from above, or something else like that. If you search for "C growable buffer", you'll find several hints on stackoverflow and via google
I have a function which returns an integer value. Now I want to write a macro which call this function, gets the return value and prepends a string to it and return the resultant string.
I have tried this:
#define TEST(x) is_enabled(x)
I call this macro in the main function as:
int ret = 0;
ret = TEST(2);
printf("PORT-%d\n", ret);
This works perfectly. However I want the macro to return the string PORT-x, where, x is the return value of the called function. How can I do this?
EDIT :
I also tried writing it into multiple lines as:
#define TEST(x)\
{\
is_enabled(x);\
}
And called it in the main function as:
printf("PORT-%d\n", TEST(2));
But this gives a compile time error:
error: expected expression before â{â token
Use a function, not a macro. There is no good reason to use a macro here.
You can solve it by using sprintf(3), in conjonction with malloc or a buffer. See Creating C formatted strings (not printing them) or man pages for details.
About your edit: You don't need to use braces {} in a macro, and they are causing your error as preprocessing would translate it to something like
printf("format%d", {
is_enabled(x);
});
To better understand macros, run gcc or clang with -E flag, or try to read this article: http://en.wikipedia.org/wiki/C_preprocessor
That's a bit of a pain since you need to ensure there's storage for the string. In all honesty, macros nowadays could be reserved for conditional compilation only.
Constants are better done with enumerated types, and macro functions are generally better as inline functions (with the knowledge that inline is a suggestion to the compiler, not a demand).
If you insist on using a macro, the storage could be done with static storage though that has problems with threads if you're using them, and delayed/multiple use of the returned string.
You could also dynamically allocate the string but then you have to free it when done, and handle out-of-memory conditions.
Perhaps the easiest way is to demand the macro user provide their own storage, along the lines of:
#include <stdio.h>
#define TEST2_STR(b,p) (sprintf(b,"PORT-%d",p),b)
int main (void) {
char buff[20];
puts (TEST2_STR(buff, 42));
return 0;
}
which outputs:
PORT-42
In case the macro seems a little confusing, it makes use of the comma operator, in which the expression (a, b) evaluates both a and b, and has a result of b.
In this case, it evaluates the sprintf (which populates the buffer) then "returns" the buffer. And, even if you think you've never seen that before, you're probably wrong:
for (i = 0, j = 9; i < 10; i++, j--)
xyzzy[i] = plugh[j];
Despite most people thinking that's a feature of for, it's very much a different construct that can be used in many different places:
int i, j, k;
i = 7, j = 4, k = 42;
while (puts("Hello, world"),sleep(1),1);
(and so on).
I'm trying to figure out there best way to define a global array with a constant size and I've come to the following options, all with their own flaws.
// 1:
#define ASIZE 10
int array[ASIZE];
// 2:
enum {ASIZE = 10};
int array[ASIZE];
// 3:
#define ASIZE_DEF 10
static const int ASIZE = ASIZE_DEF;
int array[ASIZE_DEF];
The problem with the first two is that I can't get the value of ASIZE from GDB. I guess the third option is best because I can still dump the value of the const, but it also leaks in another macro. I can undef the macro after defining the array and const but if the #define and the const are in a separate file from the array declaration, then it gets a bit hairy.
Is there a better way?
Doing something for the sake of the debugger is wrong. Incidentally, gdb knows about this if you compile your code right.
Some languages, such as C and C++, provide a way to define and invoke
“preprocessor macros” which expand into strings of tokens. gdb can
evaluate expressions containing macro invocations, show the result of
macro expansion, and show a macro's definition, including where it was
defined.
Version 3.1 and later of gcc, the gnu C compiler, provides macro
information if you specify the options -gdwarf-2 and -g3; the former
option requests debugging information in the Dwarf 2 format, and the
latter requests “extra information”.
You are dealing with a GDB issue, not a C issue. You can also do #4, which is arguably better than #3.
enum {ASIZE = 10};
static const int ASIZE_FOR_GDB = ASIZE;
int array[ASIZE];
My understanding is that you are defining a constant, using it later to size one or more arrays, and also want that constant to be a symbol, preferably without a messy namespace. (If it were a matter of exporting the size of a single array, I would instead suggest sizeof(array) / sizeof(*array) as missingno did.)
static const int ASIZE = 10;
#define ASIZE 10
int array[ASIZE];
Here, there is a variable with the desired value which will be in the object file, but the preprocessor macro shadows it with the value itself, so the array definition also succeeds.
However, you may find the need to duplicate the value expression ugly. Wouldn't it be nice if we could define the variable in terms of the macro?
static const int ASIZE =
#define ASIZE 10
ASIZE;
int array[ASIZE];
I'm not sure whether this is actually a better idea maintainability-wise than the above, but it works (and I couldn't get gcc to be offended by it) and it contains no duplication other than of the identifier. And it's amusing.
Since you know array is a global array (and not just a pointer) you can find its length using
sizeof(array) / sizeof(*array)
without needing to set an extra variable for that.