Turtle
Turtle

Reputation: 1656

Printf prints more than the size of an array

So, I'm rewriting the tar extract command, and I stumbled upon a weird problem:

In short, I allocate a HEADER struct that contains multiple char arrays, let's say:

struct HEADER {
     char foo[42];
     char bar[12];
}

When I fprintf foo, I get a 3 character-long string, which is OK since the fourth character is a '\0'. But when I print bar, I have 25 characters that are printed.

How can I do to only get the 12 characters of bar?

EDIT The fact that the array isn't null terminated is 'normal' and cannot be changed, otherwise I wouldn't have so much trouble with it. What I want to do is parse the x first characters of my array, something like

char res[13];
magicScanf(res, 12, bar);
res[12] = '\0'

EDIT It turns out the string WAS null-terminated already. I thought it wasn't since it was the most logic possibility for my bug. As it's another question, I'll accept an answer that matched the problem described. If someone has an idea as to why sprintf could've printed 25 characters INCLUDING 2 \0, I would be glad.

Upvotes: 1

Views: 1417

Answers (4)

Jonathon Reinhart
Jonathon Reinhart

Reputation: 137438

You can print strings without NUL terminators by including a precision:

printf ("%.25s", s);

or, if your precision is unknown at compilation time:

printf ("%.*s", length, s);

Upvotes: 2

pmg
pmg

Reputation: 108938

void printbar(struct HEADER *h) {
    printf("%.12s", h->bar);
}

You can use it like this

struct HEADER data[100];
/* ... */
printbar(data + 42); /* print data[42].bar */

Note that if one of the 12 bytes of bar has a value of zero, not all of them get printed.
You might be better off printing them one by one

void printbar(struct HEADER *h) {
    printf("%02x", h->bar[0]);
    for (int i = 1; i < 12; i++) printf(" %02x", h->bar[i]);
}

Upvotes: 0

Sourav Ghosh
Sourav Ghosh

Reputation: 134336

No, unless you have supplied the precision, fprintf() has no magical way to know the size of the array supplied as argument to %s, it still relies on the terminating null.

Quoting C11, chapter §7.21.6.1, (emphasis mine)

s

If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type.280) Characters from the array are written up to (but not including) the terminating null character. If the precision is specified, no more than that many bytes are written. If the precision is not specified or is greater than the size of the array, the array shall contain a null character.

So, in case your array is not null terminated, you must use a precision wo avoid out of bound access.

Upvotes: 0

JohanL
JohanL

Reputation: 6891

The problem is that the size of arrays are lost when calling a function. Thus, the fprintf function does not know the size of the array and can only end at a \0.

Upvotes: 0

Related Questions