58

What is the practical difference, if any, between stdin and STDIN_FILENO in C?

user7116
  • 63,008
  • 17
  • 141
  • 172
user1212697
  • 619
  • 1
  • 6
  • 7

5 Answers5

66

The interface. Like everyone else has said, stdin is a FILE * as defined by the standard c library. You can use some of the higher level interfaces like fread, fwrite, and fprintf. On the other hand, STDIN_FILENO is just a file descriptor (almost certainly 0). This uses a slight lower level interface through the likes of read and write.

Alan Haggai Alavi
  • 72,802
  • 19
  • 102
  • 127
Michael
  • 2,181
  • 14
  • 14
  • 37
    None of the answers mention that `STDIN_FILENO` is a macro defined in ``. At least for a POSIX compliant system, it's not just "almost certainly 0"; it's required to be defined as 0. Similarly, `STDOUT_FILENO` is 1 and `STDERR_FILENO` is 2. – Keith Thompson Apr 06 '15 at 20:32
  • 1
    The `` header [...] and the two constants `STDIN_FILENO` and `STDOUT_FILENO` are part of the POSIX standard [...]. This header contains function prototypes for many of the UNIX system services, such as the `read` and `write` functions that we call. The constants `STDIN_FILENO` and `STDOUT_FILENO` are defined in `` and specify the file descriptors for standard input and standard output. These values are `0` and `1`, respectively, as required by POSIX.1, but we’ll use the names for readability. -- Source: Advanced Programming in the Unix ® Environment - 2nd edition page 9 – Nabil Kadimi Sep 29 '18 at 19:12
24

stdin is a default FILE pointer used to get input from none other than standard in.

STDIN_FILENO is the default standard input file descriptor number which is 0. It is essentially a defined directive for general use.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
squiguy
  • 32,370
  • 6
  • 56
  • 63
12

From /usr/include/stdio.h,

/* Standard streams.  */
extern struct _IO_FILE *stdin;          /* Standard input stream.  */
extern struct _IO_FILE *stdout;         /* Standard output stream.  */
extern struct _IO_FILE *stderr;         /* Standard error output stream.  */
/* C89/C99 say they're macros.  Make them happy.  */
#define stdin stdin
#define stdout stdout
#define stderr stderr

From /usr/include/unistd.h

/* Standard file descriptors.  */
#define STDIN_FILENO    0       /* Standard input.  */
#define STDOUT_FILENO   1       /* Standard output.  */
#define STDERR_FILENO   2       /* Standard error output.  */

Ex, stdin (_IO_FILE defined in /usr/include/libio.h) is a structure data. STDIN_FILENO is a macro constant, which points to a file descriptor used by kernel.

#include <stdio.h>
#include <unistd.h>

void
stdin_VS_STDIN_FILENO(void)
{
    printf("stdin->_flags = %hd\n", stdin->_flags);
    printf("STDIN_FILENO  : %d\n", STDIN_FILENO);
}

int
main(void)
{
    stdin_VS_STDIN_FILENO();
    return 0;
}
debug
  • 991
  • 10
  • 14
1

stdin : 1. A file pointer (* FILE) 2. The file descriptor table holds its address when process is created. 3. present in /usr/include/stdio.h

STDIN_FILENO : 1. It is a macro 2. Its nothing but an array index of a file descriptor table (default 0). 3.present in /usr/include/unistd.h

Could be more clear by following code.

#include<stdio.h> 
#include<unistd.h> 
int main() 
{    
     printf("%d\t\t%p ----- ",STDIN_FILENO,stdin);

return 0; 
} 
0

The STDIN_FILENO in the linux header #include "unistd.h" is just a macro for 0 which stands for the stdin for the pipe, when you are using Linux pipe.

  • You're right, however (nitpick) pipes have nothing to do with this. The standard input is not always a pipe, for example `./command < some_file` in bash will not create a pipe. You can check whether it's a pipe or not by getting the pipe size: `fcntl(STDIN_FILENO, F_GETPIPE_SZ)` returns `-1` in this case. The same call returns `65536` (or another positive integer, ymmv) when stdin is a pipe (`cat some_file | ./command`) – Eric May 28 '22 at 11:11