C fdopen with and without -ansi

I have very little experience with gcc compilation under different environments, so please bear with me. I carried over 20 years old project into Ubuntu 18.04, it has old style K&R parameters, no function declarations to speak of, many functions without return are not declared void, and on and on...
I did a bit of cleanup and I realized that if I use -ansi then my compilation is almost 100% clean. But one simple routine complains about fdopen when I specify -ansi, without -ansi there is no complains.

Here is the code:


  $ cat f.c  
#include <stdio.h>  
#include <stdlib.h>   

FILE * my_tester(char *fname, int pnum) 
{   
  int    fd;   
  FILE *fp;      
    sprintf(fname, "/tmp/PRS.%05i.XXXXXX", pnum);         
    fd = mkstemp(fname);     
    if(fd < 0) 
    {    
         return(NULL); 
    }         
    if((fp = fdopen(fd, "w")) == NULL)     
    {         
        return(NULL);     
    }
     return(fp); 
}

   
 

Here is my compilation attempt:

  
$ cc -c -o f.o f.c  
$  
$ cc -ansi -c -o f.o f.c f.c:
 In function �my_tester': f.c:15:16: warning: assignment makes pointer from integer without a cast [-Wint-conversion]          if((fp = fdopen(fd, "w")) == NULL) 
$

I'd appreciate suggestions on what would be reasonable set of compiler flags. A simple C standards documentation covering those flags and those __USE_ macros would be much appreciated

__STRICT_ANSI__ macro is defined when you have the -ansi option set. This turns off some parts of header files that define some functions that before POSIX in 2001 were not necessarily defined in the way POSIX began to define that function's semantics. Don Cragun can probably shed more light on this issue. fdopen is in this category.

Anyway, -ansi compiled is not POSIX, so if you start working on the code you may encounter issues.

fdopen changed for POSIX AFAIK. Therefore, it gets ignored when __STRICT_ANSI__ is defined. Try

#undef __STRICT_ANSI__
/*right before */ 
#include <stdio.h>

in your code. Note this may not be a great idea, so do not decide to do major rewrites of your code.

1 Like

Jim basically has it right. With gcc -ansi gcc is being asked to supply a compilation environment as specified by an ISO C Standard. You will have to look at the gcc documentation to determine which version of the ISO C Standard that compiler flag implements.

The C Standard does not contain any definition for the fdopen () function. So, if you ask the compiler to give you a C Standard conforming environment, a function prototype for fdopen () can't be included in stdio.h .

The POSIX Standards do include a function prototype for fdopen () in stdio.h . If you want to build an application that conforms to the 2008 through 2017 versions of the POSIX Standards, you need to define the _POSIX_C_SOURCE macro to have the value 200809L before any header defined by the POSIX Standard is included and use a compiler that provides a C compiler conforming to the 1999 version of the ISO C Standard. On a UNIX, Linux, or BSD based system, this would typically be done with:

c99 -D _POSIX_C_SOURCE=200809L -o f f.c

Note also that using -c and -o in the same invocation of c99 produces unspecified results. Using both (as shown in post #1 might silently ignore one of those options, might produce a diagnostic message and do nothing else, might do whatever it was that the person who used that combination wanted to happen, or might do something else entirely at the discretion of the person who wrote the code for the compiler you're using.

Note also that using cc -o f.o f.c is always wrong. By convention a file with the extension .o is an object file created from a single source file. For example, the command:

cc -c f.c

will create a file named f.o if f.c does not contain any errors and will not create a runnable file. Using the -o . If the -c option is not included on the command line, the source files named on the command line will be compiled and the object files created from those sources file and any named object files will be linked together with default and named libraries to create a runnable file. By default that runnable file will be named a.out . The name of that runnable file can be overridden using the -o option (as shown in the c99 command I suggested above).

1 Like

fdopen may not work on platforms such as Windows where file descriptors are a weird voodoo, which is why a fully ANSI compiler wouldn't have it.

check out:

 #define  _XOPEN_SOURCE  1
#include <stdio.h>  
#include <stdlib.h>   

FILE * my_tester(char *fname, int pnum) 
{   
  int    fd;   
  FILE *fp;      
    sprintf(fname, "/tmp/PRS.%05i.XXXXXX", pnum);         
    fd = mkstemp(fname);     
    if(fd < 0) 
    {    
         return(NULL); 
    }         
    if((fp = fdopen(fd, "w")) == NULL)     
    {         
        return(NULL);     
    }
     return(fp); 
}

------ Post updated at 04:37 PM ------

question:

you are aware that fopen () only works with already open()ed file descriptors. Are you?

I don't quite understand the question, the fopen() is not used here at all. If you meant fdopen(), then yes, in this code the call to fdopen uses fd variable, which is initialized by mkstemp

He meant fdopen. I think

#define _XOPEN_SOURCE 1
#include <stdio.h>  
#include <stdlib.h>   

FILE * my_tester (char * fname, int pnum) 
{   
  int fd;   
  FILE * fp;      
    sprintf (fname, "/tmp/PRS.%05i.XXXXXX", pnum);         
    fd = mkstemp (fname);     
    if (fd <0) 
    {    
         return (NULL); 
    }         
    if ((fp = fdopen (fd, "w")) == NULL)     
    {         
        return (NULL);     
    }
     return (fp); 
}

Note that defining the feature test macro _xopen_source to have the value 1 as done by the following line in dodona's code in post #5 (and later duplicated in HongThai's code in post #8) as shown below:

#define  _XOPEN_SOURCE  1

without defining any other feature test macros asks for a programming environment that conforms to the interfaces as defined by The X/Open Portability Guide, Issue 3 (which was published in 1988). The only systems that I'm aware of that still support this programming environment are Solaris/SunOS systems distributed by Sun, Oracle, and Fujitsu.

The feature test macro I suggested in post #3 requests a much more commonly available programming environment.