In article <11*********************@b79g2000hse.googlegroups. com>
Joakim Hove <jo*********@gmail.comwrote:
>I have a function like this:
/* It actually does something else .... */
void func (int size, const char ** string_list) {
int i;
for (i=0; i < size; i++)
printf("String number %d: %s \n",i,string_list[i]);
}
And would like to (be able) to call it with a literal list of strings,
something like:
func(3 , {"String1" , "Hello", "The last string ..."});
Is that possible? ... I am more than happy to accept C99 features.
If it were more complicated you might be out of luck, but because
C's string literals are kind of funny and sort-of-primitive, you
are in luck:
void f(void) {
func(3, (const char *[]){"1", "2", "3"});
/* you can put in the array size too: (const char *[3]) */
}
>I have tried various casts like (const char **),
(const char [3][]) and (const char [3]*) but to no avail.
The thing in front of the brace list *looks* exactly like a cast,
but is not actually a cast. Instead, it is the type-specifier
part of a "compound literal".
Because the call to func() is within a block (all function calls
in C are always inside a block -- you cannot call a function
outside the outermost block of some other function), the object
created by such a call has automatic duration. In practice, this
means you get runtime code to create the array. You may get
slightly better performance if you just give in and create an
actual object, which you can then make "static":
void f(void) {
static const char *arg[] = {"1", "2", "3"};
func(3, arg);
}
In practice, this eliminates the runtime code: the array is
created at compile-time and exists before main() even gets
called. (In theory, the object could be created exactly once
when f() got called, since you would not be able to tell that
this happened. But only in theory is theory equivalent to
practice. :-) )
Of course, if you do this, you can also automatically count the
number of elements in the array:
#define NELEM(array) (sizeof array / sizeof *(array))
void f(void) {
static const char *arg[] = {"1", "2", "3"};
func(NELEM(arg), arg);
}
and of course all of this now works in C89. The only drawback is
that you must invent a name for each call, and the initialization
tends to move away from the call:
void f(void) {
static const char *argsA[] = {"1", "2", "3"};
static const char *argsB[] = {"Hello", "world"};
func(NELEM(argsA), argsA);
func(NELEM(argsB), argsB);
}
If you resort to C99's "declare anywhere" and variable argument
macros, you can solve both of those with a macro, provided you are
willing to require that each call be on a separate line:
#define PASTE(x, y) x##y
#define XPASTE(x, y) PASTE(x, y)
#define DOIT(...) \
static const char *XPASTE(args, __LINE__)[] = __VA_ARGS__; \
func(NELEM(XPASTE(args, __LINE__)), XPASTE(args, __LINE__))
(Here the PASTE and XPASTE auxiliary macros cause __LINE__ to get
expanded before token-pasting, and __VA_ARGS__ extracts what the
preprocessor sees as multiple arguments, since the comma that
separates the initializers is not protected by parentheses.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it
http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.