Functions with identical names in C - c

I am trying to compile old project, but I got an error. That project implements function dprintf, which is some kind of a printf function. However when I tried to compile that project today I found out that dprintf is already defined in stdio.h. So my question is - how to hide the standard dprintf function, because now I'm constantly getting an error like this:
ntreg.c:82: error: conflicting types for 'dprintf'
/usr/include/stdio.h:397: note: previous declaration of 'dprintf' was here
ntreg.c:93: error: conflicting types for 'dprintf'
/usr/include/stdio.h:397: note: previous declaration of 'dprintf' was here

dprintf() is not defined by the Standard.
If you configure your compiler for Standard C, the function should no longer be exposed
gcc -std=c99 -pedantic ...

Just rename your implementation to something else like
int dprintf(... parameters ...)
to
int not_stdio_dprintf(... parameters ...)
and then wherever you use it add
#define dprintf not_stdio_dprintf

Related

How does GCC compiler find the header file corresponding to some implicitly declared functions?

In the case of an implicitly declared function, gcc will sometimes tell you the header file from which the function belongs. From this answer, it seems only some functions are built in - "some compilers contain built-in declarations for them so they can do some basic type checking".
Is this how gcc is able to tell you which header file corresponds to some implicitly declared functions and not others?
For example,
implicit printf usage will generate an additional comment:
compilation.c:4:5: note: include the header <stdio.h> or explicitly provide a declaration for 'printf'
but bsearch from stdlib does not:
compilation.c:5:5: error: implicit declaration of function 'bsearch' is invalid in C99 [-Werror|,-Wimplicit-function-declaration]
how gcc is able to tell you which header file corresponds to some implicitly declared functions and not others?
Gcc has a list of symbols and headers. When the symbol is encountered and it is not defined and it is in the list, then a message is displayed with the proposed header name.
See the list at https://github.com/gcc-mirror/gcc/blob/16e2427f50c208dfe07d07f18009969502c25dc8/gcc/c-family/known-headers.cc#L157 from gcc sources.
bsearch is not in the list, so the hint is not displayed. I like the hints, it would be nice for me to include all the symbols from C standard, including bsearch. It would also be a speedup if the list would be sorted and would use bsearch. You can contribute to gcc or donate to gcc and write about it to gcc mailing list.

Who detects misspelled function name? Compiler or Linker?

According to C How to Program (Deitel):
Standard library functions like printf and scanf are not part of the C programming language. For example, the compiler cannot find a spelling error in printf or scanf. When the compiler compiles a printf statement, it merely provides space in the object program for a “call” to the library function. But the compiler does not know where the library functions are—the linker does. When the linker runs, it locates the library functions and inserts the proper calls to these library functions in the object program. Now the object program is complete and ready to be executed. For this reason, the linked program is called an executable. If the function name is misspelled, it is the linker which will spot the error, because it will not be able to match the name in the C program with the name of any known function in the libraries.
These statements leave me doubtful because of the existence of header file. These files are included during the preprocessing phase, before the compiling one, and, as I read, there are used by the compiler.
So if I write print instead of printf how can't the compiler see that there is no function declared with that name and throw an error?
If it is as the book says, why can I declare function in header files if the compiler doesn't watch them?
So if I write print instead of printf how can't the compiler see that there is no function declared with that name and throw an error?
You are right. If you made a typo in any function name, any modern compiler should complain about it. For example, gcc complains for the following code:
$ cat test.c
int main(void)
{
unknown();
return 0;
}
$ gcc -c -Wall -Wextra -std=c11 -pedantic-errors test.c
test.c: In function ‘main’:
test.c:3:5: error: implicit declaration of function ‘unknown’ [-Wimplicit-function-declaration]
unknown();
^
However, in pre C99 era of C language, any function whose declaration isn't seen by the compiler, it'll assume the function returns an int. So, if you are compiling in pre-C99 mode then a compiler isn't required to warn about it.
Fortunately, this implicit int rule was removed from the C language since C99 and a compiler is required to issue a diagnostic for it in modern C (>= C99).
But if you provide only a declaration or prototype for the function:
$ cat test.c
int unknown(void); /* function prototype */
int main(void)
{
unknown();
return 0;
}
$ gcc -c -Wall -Wextra -std=c89 -std=c11 test.c
$
(Note: I have used -c flag to just compile without linking; but if you don't use -c then compiling & linking will be done in a single step and the error would still come from the linker).
There's no issue despite the fact, you do not have definition for unknown() anywhere. This is because the compiler assumes unknown() has been defined elsewhere and only when the linker looks to resolve the symbol unknown, it'll complain if it can't find the definition for unknown().
Typically, the header file(s) only provide the necessary declarations or prototypes (I have provided a prototype for unknown directly in the file itself in the above example -- it might as well be done via a header file) and usually not the actual definition. Hence, the author is correct in that sense that the linker is the one that spots the error.
So if I write print instead of printf how can't the compiler see that there is no function declared with that name and throw an error?
The compiler can see that there is no declaration in scope for the identifier designating the function. Most will emit a warning under those circumstances, and some will emit an error, or can be configured to do so.
But that's not the same thing as the compiler detecting that the function doesn't exist. It's the compiler detecting that the function name has not been declared. The compiler will exhibit the same behavior if you spell the function name correctly but do not include a prior declaration for it.
Furthermore, C90 and pre-standardization C permitted calls to functions without any prior declaration. Such calls do not conform to C99 or later, but most compilers still do accept them (usually with a warning) for compatibility purposes.
If it is as the book says, why can I declare function in header files if the compiler doesn't watch them?
The compiler does see them, and does use the declarations. Moreover, it relies on the prototype, if the declaration provides one, to perform appropriate argument and return value conversions when you call the function. Moreover, if you use functions whose argument types are altered by the default argument promotions, then your calls to such functions are non-conforming if no prototype is in scope at the point of the call. Undefined behavior results.

Two declarations of the same function in c

I had this question in a test, and I still don't understand the answer I was given:
Let's say I wrote the following code:
#include <math.h>
#include <stdio.h>
float cos(float x){
return 1-x*x/4;
}
int main()
{
printf("%0f",cos(0.05f)+sin(0.05f));
}
Let's assume cos and sin are declared and defined in the math library (receiving and returning double), and I'm trying to link my code with the math library.
Another assumption is that cos is defined in math.c.
The question was:
"Will the code compile/link successfully? if so, which cos function
will be called?"
The answer was:
"Yes, the code will compile and my cos will be called".
How could this behavior be explained? Aren't these multiple definitions of the same function?
Your teacher may have made a mistake and intended to use double cos(double x). In this case, many C implementations will accept the program, and it will link and run because the linker takes every module from the object modules it is supplied but only takes the needed modules from the libraries it is supplied. Thus, because cos is already defined in the program, the linker will not take it from the math library. However, although this works in many C implementations, it violates the rules of standard C, which reserves the library identifiers; normal programs may not define them.
Another possibility is that your teacher did not intend to include math.h. This would make the declaration of cos not be an error, since it would not be conflicting with another declaration, but it would mean that sin should also be declared by the program, since it is used.
It will not compile.
I added a return 0; at the end of main() to remove a second problem with -Wall -Werror. If you do this you will see:
$ gcc -Wall -Werror costest1.c -o costest -lm
costest1.c:5:1: error: conflicting types for ‘cos’
This fails at the compile stage because math.h also defines a function called cos. Note the prototype for cos is:
double cos(double x);
not
float cos(float x);
If you did not include math.h, you would be able to compile, but would get:
$ gcc -Wall -Werror costest1.c -o costest -lm
costest1.c:5:1: error: conflicting types for built-in function ‘cos’ [-Werror]
costest1.c: In function ‘main’:
costest1.c:13:3: error: implicit declaration of function ‘sin’ [-Werror=implicit-function-declaration]
costest1.c:13:32: error: incompatible implicit declaration of built-in function ‘sin’ [-Werror]
cc1: all warnings being treated as errors
This is because cos is not a normal function, but handled as a builtin. As you can see it's defined in terms of sin. If cos were a normal function, you would see a duplicate symbol error of some sort.
In C you cannot have two functions with the same name even if they have different arguments. In C++ you can, in that identically named methods may differ by the calling parameters (but not just by the return type).
Online C2011 standard:
6.7 Declarations
...
Constraints
...
4 All declarations in the same scope that refer to the same object or function shall specify
compatible types
The code you posted violates the above constraint; math.h declares cos as
double cos(double x);
This behavior cannot be explained as C; it can be explained as C++, which allows for name overloading.
Make sure you're really talking about C and not C++, otherwise you are going to wind up being very confused.
EDIT:
I assume the question was about C++ and not C since compiling your code as a C program will generate conflicting types error: https://eval.in/93380.
This behaviour is caused by the Function Overloading. The cos() function has the assembly name _cos#double and redeclaring the cos() function to be accepting a float argument will have the assembly name_cos#floatand it will not conflict with the cos() defined in the math library. And calling cos() with a float argument will be translated to a call to the assembly function _cos#float which is your own cos().
Note that Function Overloading is allowed only in C++ and not C.
In C you can only do it without changing the arguments and the return types of the function (https://eval.in/93381) otherwise the previous error will be generated.
As the assumption clarifies (cos is defined in math.c), the cos() function in the case is other than the one defined in the math.h in which case the the answer would be true if it was defined to be accepting an argument of type float and returning a value of type float. In this case the program will compile without any issues.
It will not work at all.
You will see an error like this one:
conflicting types for 'cos'
I got it with codeblocks with gcc compiler ...
There is another solution you can use, please check this post: Override a function call in C
No it does not compile.
The header file math.h declares double cos(double). Attempting to overload is not allowed in C.
error C2371: 'cos' : redefinition; different basic types

mkdtemp requires _DARWIN_C_SOURCE for unistd.h

I am a little puzzled. I have project that I compile with
CFLAGS=-g -O2 -Wall -Wextra -Isrc/main -pthread -rdynamic -DNDEBUG $(OPTFLAGS) -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=700
Now I want to use mkdtemp and therefor include unistd.h
char *path = mkdtemp(strdup("/tmp/test-XXXXXX"));
On MacOSX the compilation gives some warnings
warning: implicit declaration of function ‘mkdtemp’
warning: initialization makes pointer from integer without a cast
but compiles through. While mkdtemp does return a non-NULL path accessing it results in a EXC_BAD_ACCESS.
Question 1: The template is strdup()ed and the result is non-NULL. How on earth can this result in an EXC_BAD_ACCESS?
Now further down the rabbit hole. Let's get rid of the warnings. Checking unistd.h I find the declaration hidden by the pre processor.
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
...
char *mkdtemp(char *);
...
#endif
Adding -D_DARWIN_C_SOURCE to the build makes all the problems go away but leaves me with a platform specific build. The 10.6 man page just says
Standard C Library (libc, -lc)
#include <unistd.h>
Removing the _XOPEN_SOURCE from the build makes is work on OSX but then it fails to compile under Linux with
warning: ‘struct FTW’ declared inside parameter list
warning: its scope is only this definition or declaration, which is probably not what you want
In function ‘tmp_remove’:
warning: implicit declaration of function ‘nftw’
error: ‘FTW_DEPTH’ undeclared (first use in this function)
error: (Each undeclared identifier is reported only once
error: for each function it appears in.)
error: ‘FTW_PHYS’ undeclared (first use in this function)
Question 2: So how would you fix this?
The only fix I have found is to #undef _POSIX_C_SOURCE right before the unistd.h include ...but that feels like an ugly hack.
You've asked two questions here, and I'm just going to answer the first:
Question 1: The template is strdup()ed and the result is non-NULL. How on earth can this result in an EXC_BAD_ACCESS?
As the warnings above tell you:
warning: implicit declaration of function ‘mkdtemp’
This means it couldn't find the declaration for mkdtemp. By C rules, that's allowed, but it's assuming the function returns an int.
warning: initialization makes pointer from integer without a cast
You've told the compiler "I've got a function that returns int, and I want to store the value in a char*". It's warning you that this is a bad idea. You can still do it, and therefore it compiles.
But think about what happens at runtime. The actual code you link to returns a 64-bit char*. Then your code treats that as a 32-bit int that it has to cast to a 64-bit char*. How likely is that to work?
This is why you don't ignore warnings.
And now for the second question:
Question 2: So how would you fix this?
Your problem is that you're explicitly passing -D_XOPEN_SOURCE=700, but you're using a function, mkdtemp, that isn't defined in the standard you're demanding. That means your code shouldn't work. The fact that it does work on linux doesn't mean your code is correct or portable, just that you happened to get lucky on one platform.
So, there are two rather obvious ways to fix this:
If you want to use _XOPEN_SOURCE=700, rewrite your code to only use functions that are in that standard.
If you've only added _XOPEN_SOURCE=700 as a hack that you don't really understand because it seemed to fix some other problem on linux, find the right way to fix that problem on linux.
It may turn out that there's a bug on one platform or another so there just is no right way to fix it. Or, more likely, you're using a combination of non-standard functions that can be squeezed in on different platforms with a different set of flags on each. In that case, your Makefile (or whatever drives the build) will have to pass different flags to the compiler on different platforms. This is pretty typical for cross-platform projects; just be glad you only have one flag to worry about, and aren't building 3000 lines worth of autoconf.

C error conflicting types

i have following error
error : conflicting types for 'sprintf'
error : conflicting types for 'vsprintf'
error : conflicting types for 'vprintf'
error : conflicting types for 'select'
in my header file, the code is
extern char *sprintf(char*,const char*,... )
actually i include #include <stdio.h>
but for solaries we write as
# ifndef HPUX
extern char *sprintf(char*,const char*,... )
Rather than declaring the functions yourself you should just include <stdio.h>. (If you are not trying to declare the well-known sprintf function from the standard library, but some custom function, you should choose a different name for your function).
Your declaration leads to a type conflict since the standard library function of the same name returns ìnt, not char*.
Don't manually declare standard functions, just include <stdio.h>.
(And, if you insist on declaring them yourself, at least get the type right...)
Unless you are telling the compiler to ignore standard includes (and the system C library), you probably just want to include the standard headers, i.e. as David Gelhar (the first one to answer) said.
If you are using some other C library, you would still include the standard headers, but by passing a different include path to the compiler.
You might enjoy reading up on what extern is intended to accomplish.
According to this Solaris man page (for Solaris DDI), <sys/ddi.h> defines sprintf as returning char *. It appears that this definition of the function is intended to be used only for device driver development. If you are not implementing a device driver, stick with the standard C version instead (which returns int) by including <stdio.h> and do not declare it again anywhere in your headers or source code.

Resources