Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Calling a function with a literal list of strings?

Reply
Thread Tools

Calling a function with a literal list of strings?

 
 
Joakim Hove
Guest
Posts: n/a
 
      07-31-2007
Hello,

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 have tried various casts like (const char **),
(const char [3][]) and (const char [3]*) but to no avail. I am using
gcc with std=gnu99, i.e. I am more than happy to accept C99 features.

Thank you - Joakim Hove

 
Reply With Quote
 
 
 
 
Chris Torek
Guest
Posts: n/a
 
      07-31-2007
In article <(E-Mail Removed). com>
Joakim Hove <(E-Mail Removed)> wrote:
>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 (4039.22'N, 11150.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.
 
Reply With Quote
 
 
 
 
Joakim Hove
Guest
Posts: n/a
 
      07-31-2007
Dear Chris,

thank you *very much* for a thorough and informative answer - I have
learned a lot today.

> 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".


The type-specifier of a compound literal - neat!

> 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":


I won't give in - I just love the compact calls like:

func (3 , (const char *[]) {"S" , "S2" , "..."});

which I can now use - thanks to your help. The call will be issued in
the initialization part of the code, and performance is irrelevant.

Regards

Joakim Hove


 
Reply With Quote
 
Martin
Guest
Posts: n/a
 
      08-01-2007
"Chris Torek" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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]) */
> }


gcc version 3.0.4 emits the warning:

ISO C89 forbids compound literals

--
Martin



 
Reply With Quote
 
Chris Torek
Guest
Posts: n/a
 
      08-01-2007
>"Chris Torek" <(E-Mail Removed)> wrote in message
>news:(E-Mail Removed)...
>> 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]) */
>> }


In article <vd4si.61945$(E-Mail Removed)>,
Martin <martin.o_brien@[no-spam]which.net> wrote:
>gcc version 3.0.4 emits the warning:
>
> ISO C89 forbids compound literals


Indeed. (The message might be slightly better-phrased if it said
"ISO C90" or "ANSI C89", but the meaning is clear either way.)

However, before the stuff I wrote above, I quoted the following
sentence:

>>>I am more than happy to accept C99 features.


Compound literals are a C99 feature. That GCC warns about them in
its default, neither-C89-nor-C99 not-quite-a-C-compiler compilation
mode (and/or in its C89-specific mode), is probably a good thing.

(I also described how to do the trick without using C99 features, or
with different C99 features. If you use C99 features, you must of
course have support for those in your compiler.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.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.
 
Reply With Quote
 
Martin
Guest
Posts: n/a
 
      08-01-2007

> In article <vd4si.61945$(E-Mail Removed)>,
> Martin <martin.o_brien@[no-spam]which.net> wrote:
>>gcc version 3.0.4 emits the warning:
>>
>> ISO C89 forbids compound literals

>
> Indeed. (The message might be slightly better-phrased if it said
> "ISO C90" or "ANSI C89", but the meaning is clear either way.)
>
> However, before the stuff I wrote above, I quoted the following
> sentence:
>
> >>>I am more than happy to accept C99 features.


Ah, right. I compile using

gcc -Wall -pedantic -ansi

so the warning is not surprising. And it is a warning: the code does compile
and run. But I wouldn't let that success stop me disallowing such constructs
being used at my workplace in a C89 compiler.

--
Martin



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
looping variables in a function literal 2obvious Javascript 3 10-19-2005 06:55 PM
write a function such that when ever i call this function in some other function .it should give me tha data type and value of calling function parameter komal C++ 6 01-25-2005 11:13 AM
calling virtual function results in calling function of base class... Andreas Lagemann C++ 8 01-10-2005 11:03 PM
calling virtual function results in calling function of base class ... tiwy C++ 0 01-09-2005 11:17 PM
What's wrong with rpc-literal? Why use doc-literal? Anonieko Ramos ASP .Net Web Services 0 09-27-2004 09:06 AM



Advertisments