[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Mixed initializer for char arrays?

Lauri Alanko

7/1/2011 11:29:00 AM

There are two ways to initialize a char array: with integer
expressions or with a string literal:

char foo[3] = { 102, 111, 111 };
char bar[4] = "bar";

However, I'd like to initialize the array so that its first element is
defined with a (constant) integer expression, and the rest of the
elements are defined with a string literal, i.e. something like:

char baz[4] = { 3, "baz" };

This is of course illegal. What I can do is:

char* baz = (char*)&(struct {char i; char c[3]}){ 3, "baz"};

But to my understanding there can be padding between i and c, so this
isn't fully portable. Is there a better way?


Lauri
27 Answers

Eric Sosman

7/1/2011 11:51:00 AM

0

On 7/1/2011 7:28 AM, Lauri Alanko wrote:
> There are two ways to initialize a char array: with integer
> expressions or with a string literal:
>
> char foo[3] = { 102, 111, 111 };
> char bar[4] = "bar";
>
> However, I'd like to initialize the array so that its first element is
> defined with a (constant) integer expression, and the rest of the
> elements are defined with a string literal, i.e. something like:
>
> char baz[4] = { 3, "baz" };
>
> This is of course illegal. What I can do is:
>
> char* baz = (char*)&(struct {char i; char c[3]}){ 3, "baz"};
>
> But to my understanding there can be padding between i and c, so this
> isn't fully portable. Is there a better way?

char baz[4] = "\003baz";

Note that there's no trailing '\0', because of the [4].

--
Eric Sosman
esosman@ieee-dot-org.invalid

Barry Schwarz

7/1/2011 12:06:00 PM

0

On Fri, 1 Jul 2011 11:28:56 +0000 (UTC), Lauri Alanko <la@iki.fi>
wrote:

>There are two ways to initialize a char array: with integer
>expressions or with a string literal:
>
>char foo[3] = { 102, 111, 111 };
>char bar[4] = "bar";
>
>However, I'd like to initialize the array so that its first element is
>defined with a (constant) integer expression, and the rest of the
>elements are defined with a string literal, i.e. something like:
>
>char baz[4] = { 3, "baz" };
>
>This is of course illegal. What I can do is:
>
>char* baz = (char*)&(struct {char i; char c[3]}){ 3, "baz"};
>
>But to my understanding there can be padding between i and c, so this
>isn't fully portable. Is there a better way?

Consider using an escape sequence, such as
char baz[4] = "\003baz";

--
Remove del for email

James Kuyper

7/1/2011 12:11:00 PM

0

On 07/01/2011 07:28 AM, Lauri Alanko wrote:
> There are two ways to initialize a char array: with integer
> expressions or with a string literal:
>
> char foo[3] = { 102, 111, 111 };

As a general rule, if you're going to use a character type to store
numbers, you should explicitly declare it as either 'signed' or
'unsigned', depending upon how you're going to use it. Otherwise, weird
things can happen if you port the code to a platform where plain char
has a different signedness than the one you're expecting.

> char bar[4] = "bar";
>
> However, I'd like to initialize the array so that its first element is
> defined with a (constant) integer expression, and the rest of the
> elements are defined with a string literal, i.e. something like:
>
> char baz[4] = { 3, "baz" };
>
> This is of course illegal. What I can do is:
>
> char* baz = (char*)&(struct {char i; char c[3]}){ 3, "baz"};
>
> But to my understanding there can be padding between i and c, so this
> isn't fully portable. Is there a better way?

Would this be acceptable?

char baz[4] = "\003baz";

By the way, you do realize that neither foo nor baz contains a
null-terminated string? If that wasn't deliberate, it's probably a
problem. If it was deliberate, I'd recommend adding a comment to your
code about that fact, for the benefit of future maintenance programmers.
--
James Kuyper

Lauri Alanko

7/1/2011 12:14:00 PM

0

In article <iukcba$1a2$1@dont-email.me>,
Eric Sosman <esosman@ieee-dot-org.invalid> wrote:
> > However, I'd like to initialize the array so that its first element is
> > defined with a (constant) integer expression,

> char baz[4] = "\003baz";

I see only a string literal, no integer expression.

The initializer is to be produced by a macro. The integer expression
involves sizeof, so the above approach doesn't work.

Well, except that I can do:

#define FOO(n,s) \
(n == 0 ? "\0" s : n == 1 ? "\1" s : n == 2 ? "\2" s : ....)

for 256 cases or so. This hardly seems ideal, though.


Lauri

Ike Naar

7/1/2011 1:20:00 PM

0

On 2011-07-01, Lauri Alanko <la@iki.fi> wrote:
> In article <iukcba$1a2$1@dont-email.me>,
> Eric Sosman <esosman@ieee-dot-org.invalid> wrote:
>> > However, I'd like to initialize the array so that its first element is
>> > defined with a (constant) integer expression,
>
>> char baz[4] = "\003baz";
>
> I see only a string literal, no integer expression.
>
> The initializer is to be produced by a macro. The integer expression
> involves sizeof, so the above approach doesn't work.
>
> Well, except that I can do:
>
> #define FOO(n,s) \
> (n == 0 ? "\0" s : n == 1 ? "\1" s : n == 2 ? "\2" s : ....)
>
> for 256 cases or so. This hardly seems ideal, though.

Would

char baz[4] = { 3, 'b', 'a', 'z' };

be acceptable? Or something like

#define INIT3(s) { 3, s[0], s[1], s[2] }

char foo[4] = INIT3("foo");
char bar[4] = INIT3("bar");
char baz[4] = INIT3("baz");

Mark Bluemel

7/1/2011 1:28:00 PM

0

On 07/01/2011 01:14 PM, Lauri Alanko wrote:
> In article<iukcba$1a2$1@dont-email.me>,
> Eric Sosman<esosman@ieee-dot-org.invalid> wrote:
>>> However, I'd like to initialize the array so that its first element is
>>> defined with a (constant) integer expression,
>
>> char baz[4] = "\003baz";
>
> I see only a string literal, no integer expression.
>
> The initializer is to be produced by a macro. The integer expression
> involves sizeof, so the above approach doesn't work.

Perhaps you could use a more advanced preprocessor such as "m4"?

Or could you generate (the relevant parts of) your source code from
another program?

Shao Miller

7/1/2011 6:32:00 PM

0

On 7/1/2011 6:28 AM, Lauri Alanko wrote:
> There are two ways to initialize a char array: with integer
> expressions or with a string literal:
>
> char foo[3] = { 102, 111, 111 };
> char bar[4] = "bar";
>

Hmmm...

> However, I'd like to initialize the array so that its first element is
> defined with a (constant) integer expression, and the rest of the
> elements are defined with a string literal, i.e. something like:
>
> char baz[4] = { 3, "baz" };
>
> This is of course illegal. What I can do is:
>
> char* baz = (char*)&(struct {char i; char c[3]}){ 3, "baz"};
>
> But to my understanding there can be padding between i and c, so this
> isn't fully portable. Is there a better way?

It looks like you have C99, based on your "can do" with a compound
literal. If you don't mind having roughly an equal amount of padding to
your string literals, perhaps you could use something like:

#define M_FOO_STR "foo"

#include <stdio.h>

int main(void) {
char
foo_[2][sizeof M_FOO_STR] = {
{ [sizeof M_FOO_STR - 1] = sizeof M_FOO_STR },
{ M_FOO_STR },
},
* foo = foo_[0] + sizeof M_FOO_STR - 1;
char * i = foo + 1;

printf("size: %d, chars: { ", foo[0]);
while (*i)
printf("'%c', ", *i++);
printf("'\\0' }\n");
return 0;
}

Shao Miller

7/1/2011 6:47:00 PM

0

On 7/1/2011 1:32 PM, Shao Miller wrote:
> On 7/1/2011 6:28 AM, Lauri Alanko wrote:
>> There are two ways to initialize a char array: with integer
>> expressions or with a string literal:
>>
>> char foo[3] = { 102, 111, 111 };
>> char bar[4] = "bar";
>>
>
> Hmmm...
>
>> However, I'd like to initialize the array so that its first element is
>> defined with a (constant) integer expression, and the rest of the
>> elements are defined with a string literal, i.e. something like:
>>
>> char baz[4] = { 3, "baz" };
>>
>> This is of course illegal. What I can do is:
>>
>> char* baz = (char*)&(struct {char i; char c[3]}){ 3, "baz"};
>>
>> But to my understanding there can be padding between i and c, so this
>> isn't fully portable. Is there a better way?
>
> It looks like you have C99, based on your "can do" with a compound
> literal. If you don't mind having roughly an equal amount of padding to
> your string literals, perhaps you could use something like:
>

#define M_DECL_STRING(id, string) \
char \
id ## _[2][sizeof string] = { \
{ [sizeof string - 1] = sizeof string }, \
{ string }, \
}, \
* id = id ## _[0] + sizeof string - 1

#include <stdio.h>

#define M_FOO_STR "foo"
#define M_BAR_STR "hum a few bars"

static M_DECL_STRING(foo, M_FOO_STR);
static M_DECL_STRING(bar, M_BAR_STR);

int main(void) {
char * i;

i = foo + 1;
printf("size: %d, chars: { ", foo[0]);
while (*i)
printf("'%c', ", *i++);
printf("'\\0' }\n");

i = bar + 1;
printf("size: %d, chars: { ", bar[0]);
while (*i)
printf("'%c', ", *i++);
printf("'\\0' }\n");

return 0;
}

Shao Miller

7/1/2011 7:00:00 PM

0

On 7/1/2011 1:47 PM, Shao Miller wrote:
> On 7/1/2011 1:32 PM, Shao Miller wrote:
>> On 7/1/2011 6:28 AM, Lauri Alanko wrote:
>>> There are two ways to initialize a char array: with integer
>>> expressions or with a string literal:
>>>
>>> char foo[3] = { 102, 111, 111 };
>>> char bar[4] = "bar";
>>>
>>
>> Hmmm...
>>
>>> However, I'd like to initialize the array so that its first element is
>>> defined with a (constant) integer expression, and the rest of the
>>> elements are defined with a string literal, i.e. something like:
>>>
>>> char baz[4] = { 3, "baz" };
>>>
>>> This is of course illegal. What I can do is:
>>>
>>> char* baz = (char*)&(struct {char i; char c[3]}){ 3, "baz"};
>>>
>>> But to my understanding there can be padding between i and c, so this
>>> isn't fully portable. Is there a better way?
>>
>> It looks like you have C99, based on your "can do" with a compound
>> literal. If you don't mind having roughly an equal amount of padding to
>> your string literals, perhaps you could use something like:
>>
#define M_DECL_STRING(id, string) \
char \
id ## _[2][sizeof string] = { \
{ [sizeof string - 1] = sizeof string }, \
{ string }, \
}, \
* id = id ## _[0] + sizeof string - 1

#include <stdio.h>

#define M_FOO_STR "foo"
#define M_BAR_STR "hum a few bars"

static M_DECL_STRING(foo, M_FOO_STR);
static M_DECL_STRING(bar, M_BAR_STR);

static void dump_string(char * string) {
printf("size: %d, chars: { ", *string);
while (*++string)
printf("'%c', ", *string);
printf("'\\0' }\n");
return;
}

int main(void) {
dump_string(foo);
dump_string(bar);
return 0;
}

Shao Miller

7/1/2011 7:08:00 PM

0

But beware that your string literals not exceed 'CHAR_MAX' in length, if
you are assigning a 'size_t' to a 'char'.