The size of a char array

  • Thread starter =?iso-8859-1?q?Luiz_Antonio_Gomes_Pican=E7o?=
  • Start date
?

=?iso-8859-1?q?Luiz_Antonio_Gomes_Pican=E7o?=

I have this structure:

struct some
{
int version;
char signature[3];
} some2

void main()
{
some2.version = 1;
strcpy(some2, "ihs");
}

the question is:
The signature member length is 3, but when i copy the "ihs" string to
it, the data is "ihs\0"; If i save this structure to disk, this member
will get 4 bytes. How can i avoid this ??? Thanks.
 
W

Walter Roberson

:struct some
:{
: int version;
: char signature[3];
:} some2

: strcpy(some2, "ihs");

First off, you don't want to strcpy over the whole structure, just over
the signature part of it, some2.signature

:The signature member length is 3, but when i copy the "ihs" string to
:it, the data is "ihs\0"; If i save this structure to disk, this member
:will get 4 bytes. How can i avoid this ??? Thanks.

Secondly, when you have a restricted field width, you should use
something like:

strncpy( some2.signature, "ihs", 3 );

Thirdly, the member is apparently getting 4 bytes because of
padding. There is no portable way in C to force a structure
to be unpadded (sometimes called 'packed'). If you need to store
something without padding, then you need to create a byte array
(i.e., unsigned char array) and copy the elements into place
manually:

#define some_size (sizeof(some.version) + sizeof(some.signature))
typedef char some_as_array_t[some_size];

void dosomething(void) {
some_as_array someArr;
strncpy( someArr, (char*)&some.version, sizeof(some.version) );
strncpy( someArr + sizeof(some.version), some.signature,
sizeof(some.signature) ];
fwrite( someArr, some_size, 1, OutFile );

....
some_as_array someInArr;
fread( someInArr, some_size, 1, InFile );
strncpy( (char *)&someIn.version, someInArr, sizeof( someIn.version));
strncpy( someIn.signature, someInArr + sizeof(someIn.version),
sizeof(someIn.signature) );
ver = sommeIn.version;
stnrcpy( sig, someIn.signature, sizeof(someIn.signature) );
}
 
A

Alan Balmer

I have this structure:

struct some
{
int version;
char signature[3];
} some2

void main()
{
some2.version = 1;
strcpy(some2, "ihs");
}

Did you mean strcpy(some2.signature, "ihs") ?
the question is:
The signature member length is 3, but when i copy the "ihs" string to
it, the data is "ihs\0"; If i save this structure to disk, this member
will get 4 bytes. How can i avoid this ??? Thanks.

The extra byte is not going in your structure, but writing past it in
memory. Don't do that - the results are unpredictable. Look into using
strncpy, or even memcpy.

If you write the structure to disk, it should write only sizeof(int) +
3 bytes.
 
K

Keith Thompson

Secondly, when you have a restricted field width, you should use
something like:

strncpy( some2.signature, "ihs", 3 );

Be careful with strncpy; it can leave you with an unterminated string.
(Actually not a string at all, but a character array with no trailing
'\0'.) That's ok as long as you're treating it as an array of
characters, but if you use a string function on it you'll get
undefined behavior.
 
K

Keith Thompson

Alan Balmer said:
I have this structure:

struct some
{
int version;
char signature[3];
} some2

void main()
{
some2.version = 1;
strcpy(some2, "ihs");
}
[snip]
If you write the structure to disk, it should write only sizeof(int) +
3 bytes.

The size of the structure is sizeof(struct some), which may or may not
be sizeof(int)+3. (In fact, it's very likely that there will be at
least one byte of padding at the end of the structure.)

You can read and write raw struct values to files, but don't expect
them to be readable from a program on another system, or compiled with
another compiler, or even necessarily with another version of the same
compiler.

And main() returns int, not void.
 
W

Walter Roberson

:> Secondly, when you have a restricted field width, you should use
:> something like:

:> strncpy( some2.signature, "ihs", 3 );

:Be careful with strncpy; it can leave you with an unterminated string.

Sure can -- but seeing as the OP wants to write "ihs" into a field
that only holds three characters, all the alternatives are at least
as bad.
 
A

Alan Balmer

Alan Balmer said:
I have this structure:

struct some
{
int version;
char signature[3];
} some2

void main()
{
some2.version = 1;
strcpy(some2, "ihs");
}
[snip]
If you write the structure to disk, it should write only sizeof(int) +
3 bytes.

The size of the structure is sizeof(struct some), which may or may not
be sizeof(int)+3. (In fact, it's very likely that there will be at
least one byte of padding at the end of the structure.)

But not guaranteed, of course. I should have been clearer. As you say,
at least one byte of padding is likely, but should not be counted on,
or even thought about ;-)
You can read and write raw struct values to files, but don't expect
them to be readable from a program on another system, or compiled with
another compiler, or even necessarily with another version of the same
compiler.
Yes. There are various solutions to this problem. The cleanest
portable one is to turn all values into text, with specified
delimiters.
 
E

Eric Sosman

Alan said:
I have this structure:

struct some
{
int version;
char signature[3];
} some2
[...]
If you write the structure to disk, it should write only sizeof(int) +
3 bytes.

It's unlikely but possible that there could be
padding between the `version' and `signature' elements,
so writing sizeof(int)+3 bytes wouldn't necessarily
write all the "payload" data. For bullet-proof code,
either write the two elements separately

fwrite (&some2.version, sizeof some2.version, 1, stream);
fwrite (some2.signature, sizeof some2.signature, 1, stream);

or else assemble them into a "packed" array and write that:

char buff[sizeof some2.version + sizeof some2.signature];
memcpy (buff, &some2.version, sizeof some2.version);
memcpy (buff + sizeof some2.version,
some2.signature, sizeof some2.signature);
fwrite (buff, sizeof buff, 1, stream);

If the O.P. is trying to match an externally-imposed
format, he may also need to worry about other issues: the
fact that sizeof some2.version can differ from machine to
machine, endianness problems, and so on.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,421
Latest member
StacyTaver

Latest Threads

Top