SingularInsan
SingularInsan

Reputation: 9

how to not null terminate a buffer?

Basically I want to know if there is a way to keep a null byte in a buffer?

Example:

#include <stdio.h>

int main()
{
    char buf[] = "hello there\x00, Hi";
    printf("%s\n", buf);

    return 0;
}

Unfortunately, if you compile above, the output you would get is hello there only (null terminated by \x00). So is there there a way to keep the null byte in the stack and get the Hi after that too?

FYI, if you wanted to recommend to escape \ with \\x00, I can't do that.

Upvotes: 0

Views: 1286

Answers (3)

Steve Summit
Steve Summit

Reputation: 48010

When you say

char buf[] = "hello there\x00, Hi";

the null byte and the "Hi" after them definitely are "in there". The problem is merely that printf doesn't print them, because printf always stops when it sees the first null byte. Most other standard string-handling functions will have the same problem.

You can work with strings containing null bytes if you want, but you will have to figure out your own way of keeping track of how long the string is, or where its end is, if not at the first null byte.

The usual way of dealing with "strings" of text that might contain null bytes is to use a second, separate character count variable. (This is how the standard fwrite function works, for example.) Alternatively (albeit rather nonstandardly), I have written code that detects and skips over embedded null bytes, and decides it's only really at the end of the string when it finds a pair of back-to-back null bytes.

And, no, you're right, there's no way to "escape" the null byte. It may be instructive to explain why there isn't a way, and indeed why there can't possibly be. "Under the covers", so to speak, the "null byte" is simply a byte with a value of 0. It's what all the standard C string-handling functions are looking for to determine the end of the string, and there's no way to tell any of them to use some other interpretation, to somehow ignore a hypothetically "escaped" null byte and only stop at a "real" null byte. As far as C string termination is concerned, a null byte is a null byte is a null byte.

In fact, when you write "\0" or "\x00", you're already escaping things. If you wrote "0" you'd get a length-1 string containing the character '0' (hex 0x30), and if you wrote "x00" you'd get a length-3 string containing x 0 0. It's only that backslash that turns either of these strings into one containing a literal null character. If you tried to "escape" the null character, perhaps by writing "\\0" or "\\x00", what would happen would be that you'd escape the backslash, which would take away its special meaning, meaning that it wouldn't help create a real null character, and instead you'd end up with a string containing either the two characters \ 0 or the four characters \ x 0 0.

Upvotes: 2

Vlad from Moscow
Vlad from Moscow

Reputation: 311058

If you know the actual size of the string with embedded zero characters or you know the number of substrings separated by the zero characters stored in a buffer then you can output it in parts.

For example

#include <stdio.h>
#include <string.h>

int main( void )
{
    char buf[] = "hello there\x00, Hi";
    printf("%s", buf);

    size_t n = strlen( buf );
    
    if ( n < sizeof( buf ) - 1 ) puts( buf + n + 1 ); 
    
    return 0;
}

The program output is

hello there, Hi

Upvotes: 0

tadman
tadman

Reputation: 211670

C strings by definition cannot incorporate NUL bytes, that is explicitly reserved as a terminating character. If you need a raw buffer that does support that then you can't use a C string. You will need to treat it differently. All of the C string functions starting with str are off-limits here.

printf with %s will of course terminate on the NUL byte. If you want to print the whole buffer then you need to use lower-level tools like fwrite.

Upvotes: 3

Related Questions