Standard c++ library linking

泪湿孤枕 提交于 2019-12-05 21:05:26

As a general rule in C++, it is a bad idea to manually declare library functions such as atof().

It used to be common in old C programs, but C doesn't have function overloading so it is more forgiving about "almost" correct declarations. (Well some of the old compilers were, I can't really speak for the newest ones). That is why we describe C as a "weakly typed" language, while C++ is a more "strongly typed" language.

An additional complication is that the compilers perform "name mangling": the name they pass to the linker is a modified version of the source name. The C compiler may perform quite different name mangling from the C++ compiler. The standard lib version of atof() is a C function. To declare it in a C++ source file you need to declare it as

extern "C"
{
    double atof(const char *);
}

or possibly

extern "C" double atof(const char *);

There are many additional complexities, but that is enough to go on with.

Safest idea is to just include the appropriate headers.

#include <iostream>
#include <cstdlib>

int main()
{
    const char v[]= "22";
    std::cout << "Cast result is " << atof(v) << std::endl;
    return 0;
}

Extra background in response to comment by @DmitryFucintv

  1. Calling conventions

When calling a function, a calling convention is an agreement on how parameters and return values are passed between the calling function and the called function. On x86 architecture, the two most common are __cdecl and __stdcall, but a number of others exist.

Consider the following:

/* -- f.c --*/

int __stdcall f(int a, double b, char *c)
{
    // do stuff
    return something;
}

/* main.c */

#include <iostream>
extern int __cdecl f(int a, double b, char *c);

int main()
{
    std::cout << f(1, 2.3, "45678") << std::endl;
    return 0;
}

In a C program, this will probably compile and link OK. The function f() is expecting its args in __stdcall format, but we pass them in __cdecl format. The result is indeterminate, but could easily lead to stack corruption.

Because the C++ linker is a bit fussier, it will probably generate an error like the one you saw. Most would agree that is a better outcome.

2 Name Mangling

Name Mangling (or name decoration) is a scheme where the compiler adds some extra characters to the object name to give some hints to the linker. An object might be a function or a variable. Languages that permit function overloading (like C++ and Java) must do something like this so that the linker can tell the difference between different functions with the same name. e.g.

int f(int a);
int f(double a);
int f(const char *a, ...);

It's because atof has C linkage, and you're compiling this as C++ - change:

double atof(const char*);

to:

extern "C" double atof(const char*);

and it should work.

Obviously you should not normally do this and you should just use the correct header:

 #include <cstdlib>

This has nothing to do with the standard library.

The problem you have is that atofis not being defined, so the linker doesn't find it. You need to define the function, otherwise is impossible to know what the code is supposed to do.

And it looks like atof is a C function in the header stdlib.h. This code should work, although is not using C++ exclusive functions.

#include <stdlib.h>

int main(){
    const char * v="22";
    printf("Cast result is %f", atof(v));
}

When you declare atof, you're declaring a subtly different function to the standard one. The function you're declaring is not defined in the standard library.

Don't re-declare standard functions, because you're liable to getting it wrong, as here. You're including the header and the header correctly declares the functions for you.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!