4

I want to print the content of a txt file (first parameter), but the function to do so is in a different file. I have the following main file:

#include <stdio.h>
#include <stdlib.h> 
#include <string.h>
#include "fileoperation.h"

int main(int argc, char **argv)
{
  read(argv[1]);  
    
  return 0;
}

and then in the fileoperation.c file I have:

#include "fileoperation.h"

void read(char* file)
{
  FILE *fptr;
  char c;
  fptr = fopen(file, "r");
  if (fptr == NULL)
  {
    printf("Cannot open file \n");
    exit(0);
  }

  c = fgetc(fptr);
  while (c != EOF)
  {
    printf ("%c", c);
    c = fgetc(fptr);
  }
  
  fclose(fptr);

}

If I type the code from the function in the main function, it works. I don't understand why is not working

The header file of fileoperation.c is

#ifndef FILEOPERATION_H
#define FILEOPERATION_H
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> 
#include <string.h>

void read(char* file);

#endif

carreramcl
  • 43
  • 4
  • I don't understand why it's not working either, your program looks fine. Ignore the accepted answer which is wrong. What compiler, version and OS? – Lundin Oct 27 '21 at 06:44
  • Which compiler (and OS) are you using? Are you using a Makefile or an IDE? – wovano Oct 27 '21 at 08:20

2 Answers2

7

Rename your function. read exists in the backing libraries. To make matters worse, the compiler knows what it does and optimizes it out.

Could have been worse. You could have replaced the actual read with your own and blown up the standard libraries.

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • 1
    No, this is not correct. A compiler implementation is not allowed to dump non-standard crap inside standard headers. Any compiler which does that is not compliant. Besides, I believe the old `read` function from the dinosaur ages is found in either `unistd.h` or `dos.h`, none which are standard headers or used by the OP's program. – Lundin Oct 27 '21 at 06:40
  • @Lundin: The headers are irrelevant. You can't name your function `read` or `write` or a handful of others whether or not you include the headers because the standard library calls them and if they don't do what they're supposed to do something's going to break. – Joshua Oct 27 '21 at 13:33
  • 1
    The standard library is not allowed to spew identifiers like `read` in the global namespace. If you encounter that problem, chances are that your compiler is incorrectly configured or you are using some terribly old system/compiler. – Lundin Oct 27 '21 at 13:38
0

You appear to be using a non-standard compiler, or you have configured it incorrectly. Compilers like gcc and clang are known to invoke non-compliant behavior unless you compile with -std=c17 -pedantic-errors (see What compiler options are recommended for beginners learning C?). I cannot reproduce the problem using a C compliant compiler.

A compliant compiler is not allowed to place non-standard identifiers in standard headers other than those explicitly reserved by the C standard. Examples of reserved identifiers are those with two leading underscores, those with a leading underscore followed by an upper-case letter and identifiers reserved for future language/library extensions. Source: ISO 9899:2018 chapters 4/6, 7.1.3, 6.11 and 7.31.

The mentioned compilers should remove all non-standard identifier declarations when compiling in C language compliant mode as described above. If it doesn't, you have found a compiler library bug.

There exists an old, well-known (and incredibly poorly named) function read, but it has never been part of the standard C library. (POSIX tried to standardize it but that's irrelevant here.) So the easy solution is to simply not name an identifier read - not so much because a well-known non-standard function has that name, but because it is a very poor and non-descriptive identifier name. In your case you could have used read_file or similar.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Tell me your desktop platform and I'll find a breaking function for it. – Joshua Oct 27 '21 at 13:37
  • @Joshua The whole point with technical standards is that they enforce programs to behave the same no matter platform. – Lundin Oct 27 '21 at 13:40
  • What good is a standard with 0% compliance rate? – Joshua Oct 27 '21 at 13:43
  • @Joshua But the OP's code compiles & links just fine, I tried gcc/mingw64 in Windows and gcc/godbolt on x86-64 Linux. – Lundin Oct 27 '21 at 13:47
  • It will never fail to compile. Whether or not you reproduce at runtime depends on the optimization level of libc; that is whether or not libc inlined its own internal invocation of read. The linker *will* repoint the symbol at the symbol in your executable; and it is intended that this be so; otherwise reimplementing malloc (historically a common thing to do though it's fallen out of practice) would not work. – Joshua Oct 27 '21 at 13:59
  • @Joshua If by libc you mean glibc, I believe it should fall in line if you compile as conforming C. Did you try? – Lundin Oct 27 '21 at 14:03
  • (Btw several different `read` may exist in several unrelated translation units and then the compiler/linker is expected to sort things out by internal name mangling.) – Lundin Oct 27 '21 at 14:06
  • It works with a modern glibc on my machine but fails with a classical libc. – Joshua Oct 27 '21 at 14:09
  • @Joshua And so you have a conforming C lib and you have a non-conforming C lib. I'd strongly recommend using glibc. – Lundin Oct 27 '21 at 14:12
  • It only works on glibc because it's a toy example. If any other `.a` file that calls `read` is imported it will resolve to the application's copy and explode. – Joshua Oct 27 '21 at 14:20