21

Code:

int fd;
fd = open("fruit", O_WRONLY);
write(fd, "apple", sizeof("apple"));
close(fd);

I compile it with

$ gcc test.c -o test

and run as

$ ./test   

Then I open the fruit file, and I see the following in the file:

apple^@

What does the ^@ mean?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ren
  • 2,852
  • 2
  • 23
  • 45

2 Answers2

41

It is the null character code '\0'. Certain editors like vi display it as ^@.

sizeof("apple") would return 6 because it includes the null character used to terminate strings.

frogatto
  • 28,539
  • 11
  • 83
  • 129
keety
  • 17,231
  • 4
  • 51
  • 56
39

The ^@ is the way an ASCII NUL is commonly represented in printable form. That is the same as the @ character with some bits removed:

@ = 0100
^@ = 0

and it is the same as '\0' (the string terminator in C). Because it is the string terminator, you would not see it from printf or its related functions, but you can readily create it using the block-oriented write. For example, you could have written

write(fd,"apple\0orange",sizeof("apple\0orange"));

and seen

apple^@orange^@

because every double-quoted literal in C has a trailing string terminator which is counted in its size. If you had meant to write the string without its terminator, you could have done this:

const char *s = "apple";
write(fd,s,strlen(s));

thereby eliminating two problems in the example: (a) incorrect length and (b) possibly using inconsistent string content and length by ensuring both are the same item. See Sizeof string literal for some comments on (a).

NUL is one of the 32 ASCII control characters whose values range from 0 to 31, called C0 controls. All of these ASCII control characters are typically shown in this way (for a printable form), using the character corresponding to adding 64 (0100) to the control character's value.

ASCII DEL is 127 (0177). Displaying it as ^? is a special case which is more recent than the other ASCII control characters. For instance, X/Open terminfo (curses) does not define a printable form for this character, although it does for the others. Unlike the other ASCII control characters, DEL is formed by OR'ing all (seven) bits into the character.

ASCII is a 7-bit code, of course. Many other codes were developed; ASCII corresponds to the POSIX portable character set, so it is frequently encountered.

It is easy to find tables of ASCII characters with a web search. Most of these tables (or their accompanying discussion) veer off into misinformation. Here is a link to a reasonably factual page, entitled ASCII Character Set. It states

The Control key subtracts 64 from the value of the keys that it modifies.

However, the statement is only correct if the key is one of those from the set @, A, B, etc. If you apply that to other keys, the results are perhaps interesting but not useful. Rather, in a C program you would do a logical masking, e.g.,

ch = ch & 037;

to obtain a character in the range 0 to 31.

Community
  • 1
  • 1
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • 1
    DEL too, which can be shown as `^?` (in this case with the 0x40 bit cleared rather than set). – deltab May 17 '15 at 07:01
  • Consider adding "because there is no *defined* printable form" to the 4th paragraph :) – Jongware May 17 '15 at 10:30
  • 1
    BTW—Unicode does [define](http://unicode.org/charts/PDF/U2400.pdf) symbol characters for control characters: ␀ ␡ (Your browser might not display them, though.) – Tom Blodget May 17 '15 at 12:54
  • 2
    My browser shows those in your comment, but they are in small caps, and only readable because I know what you intended. – Thomas Dickey May 17 '15 at 13:02