I'm fetching the version number of an hpux machine and trying to convert it to a float using atof, but this happens:
#include <stdio.h>
#include <sys/utsname.h>
int main(int argc, char *argv[]) {
struct utsname u;
uname(&u);
char* release = u.release;
while (*release != '.')
release++;
release++;
printf("%s\n", release);
printf("%f\n", atof(release));
}
prints this:
# ./test
11.31
0.000000
Returning double 0 just means the conversion failed. The utsname man page says the strings are null terminated, so I don't understand why the atof command is failing. Am I making some kind of obvious mistake here?
The atof function is declared in <stdlib.h>.
If you call it without the required #include <stdlib.h>, the most likely result is that (a) your compiler will print a warning (which you've apparently ignored), and (b) the compiler will assume that atof returns an int result.
Add
#include <stdlib.h>
to the top of your source file. And pay attention to compiler warnings. If you didn't get a warning, find out how to invoke your compiler in a way that makes it warn about this kind of thing. (I don't know what compiler you're using, so I can't offer specifics.) For gcc, the compiler you're using, the -Wall option will enable this warning.
Some background:
Prior to the 1999 edition of the ISO C standard, it was permitted to call a function with no visible declaration. The compiler would assume that the function takes arguments of the (promoted) types passed in the call, and that it returns a result of type int. This typically would work correctly if the function actually does return an int, and if you write the call correctly (and if the function is not variadic, like printf).
The 1999 version of the standard ("C99") dropped the "implicit int" rule, making any call to a function with no visible declaration a constraint violation, requiring a diagnostic (which can be a non-fatal warning). Many compilers, will merely warn about the error and then handle the call under the older rules. And gcc still doesn't enforce C99 rules by default; its default dialect is "GNU90", consisting of the 1990 ISO C standard plus GNU-specific extensions. You can ask it to use C99 semantics with "-std=c99"; to enforce those semantics, you can use "-std=c99 -pedantic" or "-std=c99 -pedantic-errors".
Newer versions of gcc (partially) support the latest 2011 standard if you specify "-std=c11".
See the gcc 4.8.2 manual for details.
Related
I'm new to C, just a question on strlen. I know that it is defined in <string.h>. But if I don't include <string.h> as:
#include <stdio.h>
int main()
{
char greeting[6] = { 'z', 'e', 'l', 'l', 'o', '\0' };
printf("message size: %d\n", strlen(greeting));
return 0;
}
it still works and prints 5, I did receive a warning which says warning: incompatible implicit declaration of built-in function ‘strlen’ but how come it still compile? and who provides strlen()?
There are several things going on here.
As of the 1990 version of C, it was legal to call a function without a visible declaration. Your call strlen(greeting) would cause the compiler to assume that it's declared as
int strlen(char*);
Since the return type is actually size_t and not int, the call has undefined behavior. Since strlen is a standard library function, the compiler knows how it should be declared and warns you that the implicit warning created by the call doesn't match.
As of the 1999 version of the language, a call to a function with no visible declaration is invalid (the "implicit int" rule was dropped). The language requires a diagnostic -- if you've told the compiler to conform to C99 or later. Many C compilers are more lax by default, and will let you get away with some invalid constructs.
If you compiled with options to conform to the current standard, you would most likely get a more meaningful diagnostic -- even a fatal error if that's what you want (which is a good idea). If you're using gcc or something reasonable compatible with it, try
gcc -std=c11 -pedantic-errors ...
Of course the best solution is to add the required #include <string.h> -- and be aware that you can't always rely on your C compiler to tell you everything that's wrong with your code.
Some more problems with your code:
int main() should be int main(void) though this is unlikely to be a real problem.
Since strlen returns a result of type size_t, use %zu, not %d, to print it. (The %zu format was introduced in C99. In the unlikely event that you're using an implementation that doesn't support it, you can cast the result to a known type.)
The C standard library is linked automatically. That's what gives you access to the strlen function.
Including the header file helps the compiler out by telling it what kind of function strlen is. That is, it tells it what kind of value it returns and what kind of parameters it takes.
That's why your compiler is warning you. It's saying, "You're calling this function but I haven't been told what kind of function it is." Often a compiler will make a guess. You're passing in a char[] so the compiler figures the function must take a char* as an argument. As for the return type, the compiler makes the guess that the return value is an int.
Context: In a recent conversation, the question "does gcc/clang do strlen("static string") at compile time?" came up. After some testing, the answer seems to be yes, regardless the level of optimization. I was a bit surprised to see this done even at -O0, so I did some testing, and eventually arrived to the following code:
#include <stdio.h>
unsigned long strlen(const char* s) {
return 10;
}
unsigned long f() {
return strlen("abcd");
}
unsigned long g(const char* s) {
return strlen(s);
}
int main() {
printf("%ld %ld\n",f(),g("abcd"));
return 0;
}
To my surprise, it prints 4 10 and not 10 10. I tried compiling with gcc and clang, and with various flags (-pedantic, -O0, -O3, -std=c89, -std=c11, ...) and the behavior is consistent between the tests.
Since I didn't include string.h, I expected my definition of strlen to be used. But the assembly code shows indeed that strlen("abcd") was basically replaced by return 4 (which is what I'm observing when running the program).
Also, the compilers print no warnings with -Wall -Wextra (more precisely, none related to the issue: they still warn that parameter s is unused in my definition of strlen).
Two (related) questions arise (I think they are related enough to be asked in the same question):
- is it allowed to redefine a standard function in C when the header declaring it isn't included?
- does this program behave as it should? If so, what happens exactly?
Per C 2011 (draft N1570) 7.1.3 1 and 2:
All identifiers with external linkage in any of the following subclauses … are always reserved for use as identifiers with external linkage.
If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.
The “following subclauses” specify the standard C library, including strlen. Your program defines strlen, so its behavior is undefined.
What is happening in the case you observe is:
The compiler knows how strlen is supposed to behave, regardless of your definition, so, while optimizing strlen("abcd") in f, it evaluates strlen at compile time, resulting in four.
In g("abcd"), the compiler fails to recognize that, because of the definition of g, this is equivalent to strlen("abcd"), so it does not optimize it at compile time. Instead, it compiles it to a call to g, and it compiles g to call strlen, and it also compiles your definition of strlen, with the result that g("abcd") calls g, which calls your strlen, which returns ten.
The C standard would allow the compiler to discard your definition of strlen completely, so that g returned four. However, a good compiler should warn that your program defines a reserved identifier.
I have the following program:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *tp = NULL, *cp = NULL, *next_token = NULL;
char TokenListe[] = "Hello,I Am,1";
tp = strtok_s(TokenListe, ", ", &next_token);
printf(tp);
return 0;
}
When I compile it with Visual Studio 2015 it compiles, without any warning.
But when I compile it with Dev C++ 5.11 I get the following warning in line 10:
[Warning] assignment makes pointer from integer without a cast
Is there any solution to fix that warning?
Since C11, strtok_s is now standard C, part of the optional "bounds-checking interface" (Annex K). Compilers need not support it.
But if they do, the format is this (C11 K.3.7.3.1):
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
char *strtok_s(char * restrict s1,
rsize_t * restrict s1max,
const char * restrict s2,
char ** restrict ptr);
Any other format is non-standard garbage and should not be used, including Microsoft strtok_s.
Dev C++ is no longer maintained and therefore only contains a very old version of gcc. It does not support C11, but to my knowledge, no newer version of gcc + libraries yet support the C11 bounds-checking interface either. Visual Studio is a non-conforming compiler and can't be used for compiling standard C. Generally, I would advise to use neither of these compilers, but to update to a new version of gcc (for example Codeblocks with Mingw).
Summary: strtok_s cannot be used in sensible ways. Use strtok instead. Simply ensure that all buffers involved are large enough and can't be overrun. In case of a multi-threaded program, simply don't use strtok at all.
If Dev C++ doesn't have the non-standard strtok_s, in C it will be implicitly declared, and assumed to return integer.
Note: strtok_s is in the standard, but as an "optional extension", according to (my free draft copy of the) C11 standard.
You should enable other warnings too, such as the warning for implicit declarations of functions.
If Dev C++ does contain an implementation of strtok_s, and links with it, declaring it yourself might work. But a better option is to find the right header file, or compiler flags, to get it declared, if any such options exist. Consult the documentation.
But note, as Michael Walz commented, that the strtok_s in the C11 standard and Microsoft's strtok_s are different, and don't have the same parameters! I don't know which version Dev C++ implements.
Based on the answer from #thomas-padron-mccarthy, I could fix my problem with declaring the strtok_s function in my header file.
extern char* strtok_s(char*, char*, char**);
With <stdlib.h> included the following code gives the output of 123.34.
#include<stdlib.h>
int main()
{
char *str="123.34";
float f= strtof(str,NULL);
printf("%f",f);
}
But without <stdlib.h> it produces the output of 33.000000.
What is the role of <stdlib.h> here and why did the value 33.00000 occur when it is nowhere in the code?
You must take a look at the warning generated by the compiler.
warning: implicit declaration of function 'strtof' [-Wimplicit-function-declaration]
This still yields result, which is not deterministic in any way because the return type expected is float, whereas without the header inclusion, the default is assumed to be int.
If you look into the stdlib header file, there is a declaration,
float strtof(const char *restrict, char **restrict);
With #include<stdlib.h>, we provide this declaration. When missed, compiler assumes to be returning int, and hence the result is not deterministic.
With my system, it produced 0.00000000 as the output, whereas with the necessary inclusions, I got 123.339996 as the output.
As a precaution, make a habit of always compiling the code with -Wall option (Assuming that you are using gcc), or better yet, -Werror option.
The <stdlib.h> header tells the compiler that strtof() returns a float(); in its absence, the compiler is forced to assume it returns an int. Modern C compilers (GCC 5 and above) complain about the absence of a declaration for strtof() and/or a conflict with its internal memorized declaration for strtof().
If you omit <stdlib.h>, your code is unacceptable in C99 and C11 because you didn't declare strtof() before using it. Since you omit <stdio.h>, it is invalid in C90, let alone C99 or C11. You must declare variadic functions such as printf() before using them.
Hopefully this is a very simple question. Following is the C pgm (test.c) I have.
#include <stdio.h>
//#include <stdlib.h>
int main (int argc, char *argv[]) {
int intValue = atoi("1");
double doubleValue = atof("2");
fprintf(stdout,"The intValue is %d and the doubleValue is %g\n", intValue, doubleValue);
return 0;
}
Note that I am using atoi() and atof() from stdlib.h, but I do not include that header file. I compile the pgm (gcc test.c) and get no compiler error!
I run the pgm (./a.out) and here is the output, which is wrong.
The intValue is 1 and the doubleValue is 0
Now I include stdlib.h (by removing the comments before the #include) and recompile it and run it again. This time I get the right output:
The intValue is 1 and the doubleValue is 2
How come the compiler did not complain about not including the stdlib.h and still let me use the atoi(), atof() functions?
My gcc info:
$ gcc --version
gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)
Any thoughts appreciated!
For historical reasons -- specifically, compatibility with very old C programs (pre-C89) -- using a function without having declared it first only provokes a warning from GCC, not an error. But the return type of such a function is assumed to be int, not double, which is why the program executes incorrectly.
If you use -Wall on the command line, you get a diagnostic:
$ gcc -Wall test.c
test.c: In function ‘main’:
test.c:5: warning: implicit declaration of function ‘atoi’
test.c:6: warning: implicit declaration of function ‘atof’
You should use -Wall basically always. Other very useful warning options for new code are -Wextra, -Wstrict-prototypes, -Wmissing-prototypes, -pedantic, and -Wwrite-strings, but compared to -Wall they have much higher false positive rates.
Tangentially: never use atoi nor atof, they hide input errors. Use strtol and strtod instead.
If you don't specify otherwise, I believe a C compiler will just guess that undeclared functions take the form extern int foo(). Which is why atoi works and atof doesn't. Which compiler flags were you using? I suggest using -Wall to turn on a bunch of gcc warnings, which should include referencing undeclared functions.
C allows you to call a function without having a declaration for that function.
The function will be assumed to return an int and arguments will be passed using default promotions. If those don't match what the function actually expects, you'll get undefined behavior.
Compilers will often warn for this case, but not always (and that will also depend on compiler configuration).
In C, when you use a function that was not declared, it assumes that it has the default prototype:
int FUNCTION_NAME();
Note that in C using () as prototype means it accepts any arguments.
If you compile with the flag -Wall (I recommend you to always use this flag, since it enables all recommended warnings) you will get a warning (not an error) telling you that you are using an undeclared function.
C, unfortunately, does not require functions to be prototyped (or even declared) before use -- but without a prototype, it automatically makes certain assumptions about the function. One of those is that it returns an int. In your case, atoi does return an int, so it works correctly. atof doesn't, so it doesn't work correctly. Lacking a prototype/declaration, you get undefined behavior -- typically it'll end up retrieving whatever value happens to be in the register where an int would normally be returned, and using that. It appears that in your particular case, that happens to be a zero, but it could just as easily be something else.
This is one of the reasons many people push "C++ as a better C" -- C++ does require that all functions be declared before use, and further that you specify the types of all (non-variadic) parameters as well (i.e. a C++ function declaration is like a C prototype, not like a C declaration).