45

I know that EOF and '\0' are of type integers, but if so shouldn't they have a fixed value?

I printed both and got -1 for EOF and 0 for '\0'. But are these values fixed?

I also had this

int a=-1;

printf("%d",a==EOF); //printed 1

Are the value for EOF and '\0' fixed integers?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
theReverseFlick
  • 5,894
  • 8
  • 32
  • 33
  • Note: The '\\' in a character literal denotes an escape sequence. Thus '\0' is an octal escape sequence whose value is 0. – Martin York Jan 16 '11 at 18:17
  • 4
    In C, `EOF` and `'\0'` are expressions of type `int`. Saying they're "of type integers" doesn't make much sense; `int`, `long`, `unsigned char` and so forth are all integer types. (Though the name `int` originated as an abbreviation for "integer", "integer" in C is a more inclusive term than `int`.) – Keith Thompson Jun 11 '13 at 18:36

5 Answers5

70

EOF is a macro which expands to an integer constant expression with type int and an implementation dependent negative value but is very commonly -1.

'\0' is a char with value 0 in C++ and an int with the value 0 in C.

The reason why printf("%d",a==EOF); resulted in 1 was because you didn't assign the value EOF to a. Instead you checked if a was equal to EOF and since that was true (a == -1 == EOF) it printed 1.

Risadinha
  • 16,058
  • 2
  • 88
  • 91
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • But how can I differentiate between NULL and 0 then if there is such a need? – theReverseFlick Jan 16 '11 at 14:52
  • 2
    @ShyamLovesToCode: You can't necessarily distinguish between 0 and NULL because NULL might expand to 0. I can't see how or why would you need to, can you clarify? – CB Bailey Jan 16 '11 at 14:54
  • 5
    @Shyam - Why is there such a need? Use `NULL` if you're talking about pointers, `'\0'` if you're talking about characters and use `EOF` when checking for the end of a file. Doing this makes your code less confusing. – OrangeDog Jan 16 '11 at 14:55
  • I have an integer array, each element can take any value within the integer range. Now I want to differentiate some elements among them but storing a different value, I thought I could store NULL but then what if there is a confusion between 0 and NULL – theReverseFlick Jan 16 '11 at 14:56
  • Or may be because NULL is a void * , I can store \0, but still the same problem exists? Correct where I'm going wrong – theReverseFlick Jan 16 '11 at 15:00
  • 4
    @ShyamLovesToCode: If each integer can take any value within its range then, by definition, no valid integer can be a sentinel value. If you want to store a "not a value" flag, you will have to do this with additional data items. – CB Bailey Jan 16 '11 at 15:02
  • @OrangeDog Good explanation :) So how do you think I should go about with the issue? – theReverseFlick Jan 16 '11 at 15:02
  • @Charles Yes may be that's the only way to go – theReverseFlick Jan 16 '11 at 15:03
  • 2
    If being able to store any integer value is a requirement you will need an additional data structure. If being able to store almost any integer value is ok then you can use INT_MAX to denote invalid data. – James Greenhalgh Jan 16 '11 at 15:14
  • @Charles, what you're saying is right, and yet both C and C++ have a small problem with that (that has everything to do with implementation, but still...): If pointers are represented as 32-bit numbers on a platform with 32-bit address space, it immediately follows that there will be a single address which you won't be able to access normally, since it will be what NULL expands to. Many implementations use 0, as most software pieces don't access address 0 (and those who do do it in Assembly), but it still smells. – conio Jan 16 '11 at 22:43
  • 1
    @Shyam - I generally use `INT_MIN` as the invalid value in this case. This has the pleasing side-effect of making the integers symmetric. However if you need to have all `int`s as possible values then you'll need a structure with an additional "invalid" flag. – OrangeDog Jan 16 '11 at 23:13
30

NULL and '\0' are guaranteed to evaluate to 0, so (with appropriate casts) they can be considered identical in value; notice however that they represent two very different things: NULL is a null (always invalid) pointer, while '\0' is the string terminator. EOF instead is a negative integer constant that indicates the end of a stream; often it's -1, but the standard doesn't say anything about its actual value.

C & C++ differ in the type of NULL and '\0':

  • in C++ '\0' is a char, while in C it's an int; this because in C all character literals are considered ints.
  • in C++ NULL is "just" an integral 0, while in C it can be defined as a 0 casted to void *; this cannot be done in C++ (and it's explicitly forbidden in a note) because, being C++ more strict in pointer conversions, a void * is not implicitly convertible to any other pointer type, so, if NULL was a void *, it would be necessary to cast it to the target pointer type on assignment:

    int * ptr = (void *) 0; /* valid C, invalid C++ */
    

Relevant standard quotations:

C++98/03

NULL

NULL is an integer type guaranteed to evaluate to 0:

4.10 Pointer conversions

A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of pointer to object or pointer to function type. Two null pointer values of the same type shall compare equal. The conversion of a null pointer constant to a pointer to cv-qualified type is a single conversion, and not the sequence of a pointer conversion followed by a qualification conversion (4.4).

18.1 Types

[...] The macro NULL is an implementation-defined C++ null pointer constant in this international Standard (4.10). (Possible definitions include 0 and 0L, but not (void*)0).

'\0'

A 0-value char must exist:

2.2 Character sets

The basic execution character set and the basic execution wide-character set shall each contain [...] a null character (respectively, null wide character), whose representation has all zero bits.

'\0' is a char literal:

2.13.2 Character literals

A character literal is one or more characters enclosed in single quotes, as in 'x', optionally preceded by the letter L, as in L’x’. A character literal that does not begin with L is an ordinary character literal, also referred to as a narrow-character literal. An ordinary character literal that contains a single c-char has type char, with value equal to the numerical value of the encoding of the c-char in the execution character set.

and it's value is 0, since that escape sequence specifies its value:

The escape \ooo consists of the backslash followed by one, two, or three octal digits that are taken to specify the value of the desired character.

'\0' is used to terminate strings literals:

2.13.4 String literals

After any necessary concatenation, in translation phase 7 (2.1), '\0' is appended to every string literal so that programs that scan a string can find its end.

EOF

The definition of EOF is delegated to the C89 standard (as stated in §27.8.2 "C Library files"), where it is defined as an implementation specific negative integer.

C99

NULL

A null pointer is a 0 integer, optionally casted to void *; NULL is a null pointer.

6.3.2.3 Pointers

[...] An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. (The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

7.17 Common definitions <stddef.h>

[...] The macros are

NULL

which expands to an implementation-defined null pointer constant; [...]

'\0'

'\0' is an integer with value 0, and is used to terminate strings:

5.2.1 Character sets

[...] A byte with all bits set to 0, called the null character, shall exist in the basic execution character set; it is used to terminate a character string.

6.4.4.4 Character constants

An integer character constant is a sequence of one or more multibyte characters enclosed in single-quotes, as in 'x'. [...]

The octal digits that follow the backslash in an octal escape sequence are taken to be part of the construction of a single character for an integer character constant or of a single wide character for a wide character constant. The numerical value of the octal integer so formed specifies the value of the desired character or wide character. [...]

An integer character constant has type int.

EOF

EOF is an implementation-defined negative integer

7.19 Input/output <stdio.h>

7.19.1 Introduction

EOF

which expands to an integer constant expression, with type int and a negative value, that is returned by several functions to indicate end-of-file, that is, no more input from a stream

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • 1
    In C, `NULL` doesn't necessarily evaluate to `0` after conversion. If `NULL` is defined as `((void*)0)`, then `(int)NULL` may or may not evaluate to `0`. There's a special-case rule for converting a constant integer expression to a pointer type (that's part of the definition of a *null pointer constant*), but there's no such rule in the opposite direction. On a rare implementation where a null pointer is not represented as all-bits-zero, converting a null pointer to an integer type is likely to give you a non-zero value. But `NULL == 0` is true, because `0` is converted to a pointer if needed. – Keith Thompson Jun 11 '13 at 18:40
  • The above comment is a quibble, and is not particularly relevant in most cases. – Keith Thompson Jun 11 '13 at 18:41
6

'\0' is always the null character, or 0. EOF depends on the compiler, but is usually -1, and always is a value that an unsigned char can't hold. Don't rely on the value of EOF being anything, because it CAN CHANGE. Always do x == EOF not x == -1. The value of '\0' is ALWAYS 0. You can count on that.

Leo Izen
  • 4,165
  • 7
  • 37
  • 56
  • 2
    `EOF` is of type `int`. Since it's negative, it's by definition a value that an `unsigned char` can't hold. But since it's possible for `unsigned char` and `int` to have the same size (if `CHAR_BIT >= 16`), it may not be possible to distinguish between `EOF` and a valid result from `getchar()`. That's a drawback of in-band signalling. But it's 99.99+% safe to ignore that, since the only real-world systems with `CHAR_BIT >= 16` are DSPs, and you're not going to expect portable I/O code to run on such a system anyway. – Keith Thompson Jun 11 '13 at 18:48
0

Yes, they are. '\0' has the same value of NULL which is 0 (but they mean different things), while EOF is usually -1.

printf("%d",a==EOF); //printed 1

In this case you are asking: is a == EOF? if it is print 1 (which is true), it it's not print 0 (which is false).

BlackBear
  • 22,411
  • 10
  • 48
  • 86
  • Yes I just wanted to ask if EOF is -1 always – theReverseFlick Jan 16 '11 at 14:51
  • 1
    `'\0'` and `NULL` may happen to have always the same value, but they have a very different meaning. `'\0'` is the string terminator, while `NULL` is a null (invalid) pointer. – Matteo Italia Jan 16 '11 at 14:52
  • @ShyamLovesToCode: usually it is. – BlackBear Jan 16 '11 at 14:52
  • But what if there is a requirement to differentiate between EOF and -1? – theReverseFlick Jan 16 '11 at 14:54
  • @BlackBear: but it's not guaranteed so; `EOF` *expands to an integer constant expression, with type int and a negative value, that is returned by several functions to indicate end-of-file, that is, no more input from a stream* (C99, §7.19.1:3). -EDIT- Well edited. :) – Matteo Italia Jan 16 '11 at 14:55
  • @on_the_edge: If you need to distinguish between the value of `EOF` and the `int` value `-1`, you need to reexamine your requirements; they're indistinguishable on the majority of implementations that define `EOF` as `(-1)`. If you need to distinguish between them in your source code, you do so by writing `EOF` or `-1` in the proper context. – Keith Thompson Jun 11 '13 at 18:45
-1

'\0' is always 0

EOF is compiler dependent

most commonly its -1 (in gcc & g++ it is -1).

Kumar Alok
  • 2,512
  • 8
  • 26
  • 36
  • 1
    `\0` is **never** `NULL` (In C, the former is an `int` and the latter is a pointer; in C++, the former is a `char` and the latter is an int/pointer/char depending on context). I realize that your answer is still strictly true according to boolean algebra but it’s completely misleading and any mention of `NULL` as done here is irrelevant. – Konrad Rudolph Jan 16 '11 at 14:55
  • @Konrad: you're wrong: `NULL` evaluates to an implementation-defined null pointer constant, ie a integer constant expression with value 0, or - in C - such an expression cast to `void *`; `'\0'` is a valid null pointer constant and compares equal to `NULL` – Christoph Jan 16 '11 at 14:58
  • @KonradRudolph: Why can't `NULL` be `\0` in C++? It would seem like a valid definition to me. Integral constant expression (check), _rvalue_ (check), evaluates to zero (check). – CB Bailey Jan 16 '11 at 14:59
  • @Charles `\0` is a `char`. There is no reason `NULL` should be implemented in terms of it. While it’s true that C++ lax conversion rules *allow* for this it’s just nonsensical and IMHO very misleading in an answer to the question what the value of `\0` is. – Konrad Rudolph Jan 16 '11 at 15:12
  • @Christoph: “compares equal to” is a fundamentally different statement than “is always”. In particular, it’s an artifact of C++’ weak typing, not a *causal* relation as implied by the original formulation in this answer. I very much prefer the updated answer: “'\0' is always 0” – no need to mention `NULL` here at all. – Konrad Rudolph Jan 16 '11 at 15:14
  • @KonradRudolph: It's legal, but silly, for a C or C++ implementation to have `#define NULL '\0'`. On the other hand, as a matter of programming style, `NULL` should be used only when a null pointer is required, and `'\0'` should be used only when a null character is required. – Keith Thompson Jun 11 '13 at 18:43