Why does strtof always output 0.0000? - c

Calling strtof with a floating point number runs fine on my local machine but on the school's servers strtof always returns 0.000000. I checked to see if there was anything stored in errno since a 0 should mean an error, but it says success. Does anyone have an idea why this might be?
Here is the code.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("%f\n", strtof(argv[1],0));
return 0;
}

Short version: compile with -std=gnu99 or -std=c99. Explanation follows.
I've reproduced a similar "problem" on my own box. However, when I try to compile:
# gcc -Wall -o float float.c
float.c: In function 'main':
float.c:6: warning: implicit declaration of function 'strtof'
float.c:6: warning: format '%f' expects type 'double', but argument 2 has type 'int'
So I looked at the man page for strtof(), and it says:
SYNOPSIS
#include <stdlib.h>
double strtod(const char *nptr, char **endptr);
#define _XOPEN_SOURCE=600 /* or #define _ISOC99_SOURCE */
#include <stdlib.h>
float strtof(const char *nptr, char **endptr);
long double strtold(const char *nptr, char **endptr);
What that means is that one of those values has to be #defined before including stdlib.h. However, I just recompiled with -std=gnu99, and that defines one of those for me and it works.
# gcc -std=gnu99 -Wall -o float float.c
# ./float 2.3
2.300000
Moral: always compile with -Wall. ;-)

Have you included the header where strtof is defined (stdlib.h), otherwise you may get 0.0 since by default unknown functions in C are treated as returning int.

Related

Why does strtof not print proper float?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char aaa[35] = "1.25";
char* bbb = &(aaa[0]);
char** ccc = &(bbb);
float a = strtof(*ccc, ccc);
printf("%f\n", a);
return 0;
}
The code I wrote above should print 1.25, but according to codepad (online C compiler), it does not print 1.25. On codepad, it prints 2097152.000000 . Here's the codepad link
What have I done wrong here?
codepad has an old version of gcc, and presumably of the standard C library. Apparently, strtof is not being declared by the header files you include. (strtof was added in C99.)
Try using an online service with a postdiluvian version of gcc. Or explicitly add the correct declaration:
float strtof(const char* ptr, char** end_ptr);
What's happening is that without the declaration, the compiler defaults the return type of the function to int. Since the function actually returns a float, the float is being interpreted as (not converted to) an integer, and then that integer is converted to a float.
No warning is produced, presumably because -Wall is not in the compiler options, and/or the C standard being used allows the use of non-declared functions.

strfry(char *__string) returns int?

So I'm new to C and I'm playing around with functions in the GNU C Library when I come across https://www.gnu.org/software/libc/manual/html_node/strfry.html#strfry
Intrigued, I wrote a little tester program:
1 #include <stdio.h>
2 #include <string.h>
3
4 main ()
5 {
6 char *str = "test123abc";
7 char *other;
8
9 other = strfry(str);
10 printf("%s\n", other);
11 return 0;
12 }
gcc test.c outputs test.c:9: warning: assignment makes pointer from integer without a cast
Why?
/usr/include/string.h has the following entry:
extern char *strfry (char *__string) __THROW __nonnull ((1));
How can a char *function(...) return int?
Thanks
Since strfry is a GNU extension, you need to #define _GNU_SOURCE to use it. If you fail to provide that #define, the declaration will not be visible and the compiler will automatically assume that the function returns int.
A related problem, as pointed out by perreal, is that it is undefined behavior to modify a literal string. Once you make the declaration of strfry visible to the compiler, this will be duly reported.
Do note that the strfry function and its cousin memfrob are not entirely serious and are rarely used in production.
To have strfry available, you need
#define _GNU_SOURCE
otherwise the prototype is not exposed and the implicit declaration is assumed to return an int.
The problem is you don't have a prototype in scope for strfry() and the compiler assumes it returns an int. When it wants to assign that int to a char* it complains with the message you specify.
According to my man pages, you need to #define _GNU_SOURCE at the very top of your source code, especially before standard #includes
#define _GNU_SOURCE
/* rest of your program */
You can't modify a literal string:
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
int main () {
char *str = "test123abc";
char other[256];
strcpy(other, str);
strfry(other);
printf("%s\n", other);
return 0;
}

Why can I assign a string to a pointer to float?

Why is the code below working? Should that be a compilation error (or at least a run-time error)?
#include <stdio.h>
int main(int argc, char** argv){
float *buf = "happy holiday"; // notice the float
printf("content of buf = %s\n",buf); //its working
return 0;
}
I compiled it and got just a warning:
~/Desktop/cTest>gcc -o run run.c
run.c: In function `main':
run.c:4: warning: initialization from incompatible pointer type
You should always compile with -Wall -Werror -Wextra (at a minimum). Then you get this:
cc1: warnings being treated as errors
test.c: In function 'main':
test.c:4: warning: initialization from incompatible pointer type
test.c:5: warning: format '%s' expects type 'char *', but argument 2 has type 'float *'
test.c: At top level:
test.c:3: warning: unused parameter 'argc'
test.c:3: warning: unused parameter 'argv'
It "works" because in practice, there's no difference between a char * and a float * under the hood on your platform. Your code is really no different to:
#include <stdio.h>
int main(int argc, char** argv){
float *buf = (float *)"happy holiday";
printf("content of buf = %s\n",(char *)buf);
return 0;
}
This is well-defined behaviour, unless the alignment requirements of float and char differ, in which case it results in undefined behaviour (see C99, 6.3.2.3 p7).
This program is not strictly conforming, a compiler is required to output a diagnostic and has the right to refuse to compile it. So don't do it.
This is an unfortunate behavior of gcc, and if somebody could get it fixed, we'd all be dealing with a lot less buggy software. Unfortunately there's a lack of will to fix many things like this. Submitting a bug report would not hurt.

Array Arithmetic Issue in C

I have a C code in long file that is compiled using cc. But when I tried to compile on gcc it gives error. I took that particular code in small program and try to compile on cc but it failed over there.
Here is source:
#include <stdio.h>
int main (int argc, char **argv)
{
char unsigned FileName[100];
char test[100];
FileName[strstr(FileName,test) - FileName] = 0;
return 0;
}
This line is causing the problem:
FileName[strstr(FileName,test) - FileName] = 0;
error on CC is :
"foo.c", line 10: operands have incompatible types:
int "-" pointer to unsigned char
and on gcc is :
foo.c:10: error: invalid operands to binary - Both are same.
But when I compile original file on CC it compiled and just give a warning. Like this:
"dbtprc.c", line 643: warning: argument #1 is incompatible with prototype:
prototype: pointer to const char : "/usr/include/iso/string_iso.h", line 133
argument : pointer to unsigned char
"dbtprc.c", line 643: warning: improper pointer subtraction
Can you please help why here it is giving warning "improper pointer subtraction" and sample program it is showing error?
Don't you missed to include <string.h> ??
If yes, the prototype of strsrt is guessed and by default it returns an int, hence the invalid pointer operation.
Otherwise, it appears that the signedness mismatch is the cause of the warning/error.
Use a (char*)cast before the two occurence of your table and it will go.
Is there anything called Array Arithmetic in C? Read this:
Arrays are not Pointers.
And see how to use strstr().
void * bar;
void * foo;
...
foo = bar + 1;
That's undefined behaviour, right there! You are referring to a memory location that wasn't even allocated.
EDIT:
Now you have another problem: even though you sucessfully declared both arrays, you failed to clean/initialize them. Only god knows what strstr() will return to you.
The problem you have compiling this code is that strstr() takes 2 const char* and you defined Filename as unsigned: char unsigned FileName[100];
char *strstr(const char *haystack, const char *needle);
An error or a warning is not much different, just showing how serious the compiler believes the issue is.
But why do you use unsigned char for the filename? That's in conflict with strstr which only handles char*, both for its parameter and return type.
That's what the compilers try to tell you, in different ways.

why is strtof is always evaluating to HUGE_VAL?

What could be the issue here? It doesn't matter what number I choose for str, it is always 26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168192.00
char *str = "2.6";
printf("%f\n", strtof(str, (char**)NULL));
//prints 26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168192.00
whole program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *str = "2.6";
printf("%f\n", strtof(str, NULL));
return 1;
}
compile with -Wall:
test4.c:7: warning: implicit declaration of function âstrtofâ
What platform are you building for/on? The warning that you say is being emitted:
test4.c:7: warning: implicit declaration of function âstrtofâ
indicates that the compiler doesn't know that strtof() returns a float, so it's going to push an int to the printf() call instead of a double. strtof() is normally declared in stdlib.h, which you're including. But it wasn't a standard function until C99, so the exact compiler platform (and configuration/options you're using) may affect whether it's being made available or not.
strtof is defined in C99 only. It may be that passing the option -std=c99 to the compiler will fix it since default GCC (-std=gnu89) includes only a few C99 features.
Another option is to use the C89-kosher strtod. Which is probably the better option in the long run, anyways. (When do you need singles except in exceptional circumstances?)
Perhaps you've forgotten to include the correct header(s)?
#include <stdlib.h>
#include <stdio.h>
int main() {
printf("%f\n", strtof("2.6", NULL));
return 0;
}
produces:
2.600000
for me...
Given your warnings, you should try adding -std=c99 to get the C99 standard definitions from the header. By default it will assume that the return value is an int and then try to convert that to a float. This will obviously be wrong. Alternatively you could simply supply your own, correct declaration for strtof().
As the others have said, you need -std=c99. But you can also use strtod() which is string to double, and you don't need -std=c99 for that.
I was having problems with strtof() on CentOS 5.5 with glibc 2.5 unless I used -std=c99, but strtod() worked perfectly.

Resources