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.
Related
I know I shouldn't define any function like that. But I like to try the limits, so I wrote some code like that:
#include <stdio.h>
void func(a)
{
printf("%d\n", a);
}
int main()
{
func();
func();
func();
return 0;
}
I really wasn't looking for any outputs, but the one I saw was very odd.
The output is
1
0
0
Why? Where did those 1's or 0's came from?
(I'm using CygWin & Eclipse duo btw.)
Your program is invalid.
gcc 8.2 complains:
$ gcc -Wall -Wextra -pedantic -std=c17 t.c
test.c: In function ‘func’:
test.c:3:6: warning: type of ‘a’ defaults to ‘int’ [-Wimplicit-int]
void func(a)
Since C99, all functions require their arguments to have valid types (there used to be "implicit int" rule - function argument/return types are assumed int if not specified). But your program is not valid in C89 either because you don't actually pass any argument. So what you see is the result of undefined behaviour.
Prior to the 1989 ANSI C standard, the only way to define a function in C did not specify the number and types of any parameters. (This old version of the language is called "K&R C", since it's described in the first edition of The C Programming Language by Kernighan and Ritchie.) You're using an old-style function definition:
void func(a)
{
printf("%d\n", a);
}
Here a is the name of the parameter. It is implicitly of type int, but that information is not used in determining the correctness of a call to func.
C89 added prototypes, which allow you to specify the types of parameters in a way that is checked when the compiler sees a call to the function:
void func(int a)
{
printf("%d\n", a);
}
So in the 1989 version of the C language, your program is legal (in the sense that there are no errors that need to be diagnosed at compile time), but its behavior is undefined. func will probably grab whatever value happens to be in the location in which it expects the caller to place the value of the argument. Since no argument was passed, that value will be garbage. But the program could in principle do literally anything.
The 1999 version of the language dropped the "implicit int" rule, so a is no longer assumed to be of type int even with the old-style definition.
But even the latest 2011 version of C hasn't dropped old-style function definitions and declarations. But they've been officially obsolescent since 1989.
Bottom line: Always use prototypes. Old-style function definitions and declarations are still legal, but there is never (or very rarely) any good reason to use them. Unfortunately your compiler won't necessarily warn you if you use them accidentally.
(You're also using an old-style definition for main. int main() is better written as int main(void). This is less problematic than it is for other functions, since main is not normally called, but it's still a good habit.)
When you don't define type for the variables int is taken as default type by compiler.
warning: type of 'a' defaults to 'int' [-Wimplicit-int]
void func(a)
Hence it is printing indeterminate values which int a contains.
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.
Hi after going through answer here
1: Do I cast the result of malloc? I understood that one of the reason why we do not cast malloc is that
casting malloc is redundant
But what I am still trying to figure out is the warning that will be suppressed when we do cast the malloc function
I also read this answer but I have the follwing doubts
#include<stdio.h>
main()
{
int *a=malloc(20);
}
I understood the point in the answer that compiler will think that malloc returns an int while we are trying to give that value to an int * which will gives us error cannot convert from int * to int or something like that but the basic question is
Won't the compiler in absence of stdlib.h treat malloc as a user defined function and wont it look for the declaration of it and it will give some error related to missing delcaration/defination
In the original C language - C89/90 - calling an undeclared function is not an error. For this reason, a pre-C99 compiler will not produce any "error" due to a missing function declaration. The compiler will simply assume that function returns an int.
It will also automatically and quietly "guess" (infer, derive) the function parameter types from the argument types you supplied in your call. In your example, you supplied 20, which will make the compiler to guess that the "unknown" malloc function takes a single parameter of type int. Note that this is also incorrect, because the real malloc takes a size_t parameter.
In C99 and later the function declaration is required. Which means that forgetting to declare malloc (e.g. forgetting to include <stdlib.h>) is indeed an error, which will result in a diagnostic message. (The parameter-guessing behavior is still there in the language though.)
Note also that in C99 and later declaring function main without an explicit return type int is illegal. The "implicit int" rule is specific to the original version of C language specification only. It no longer exists in C99 and later. You have to declare it as int main(... explicitly.
In the absence of stdlib.h the compiler thinks that the malloc() function will return int(For C89/90 and not from c99) and you are trying to assign that value to int * and hence there is a type mismatch and the compiler will report it
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.
I'm reading a bit of code in C, and in the variable declaration line, there's "char *p, *getenv();"
I understand "char *p" of course. What does "char *getenv()" do? Later on in the code, the function getenv() is called with a variable passed to it. But what's the point of "char *getenv();" without any arguments?
Sorry if this is basic. I'm just starting to learn C.
It is "valid C" (I would almost say "unfortunately") - but it is not particularly useful. It is a "declaration without declaration" - "I will be using a function getenv() but I'm not going to tell you what the arguments will be". It does have the advantage of preventing a compiler warning / error - something that would normally be prevented with a "real" function prototype, for example by including the appropriate .h file (in this case, stdlib.h).
To clarify: the following code
#include <stdio.h>
int main(void) {
char *p;
p = getenv("PATH");
printf("the path is %s\n", p);
return 0;
}
will throw a compiler warning (and you should never ignore compiler warnings):
nonsense.c: In function ‘main’:
nonsense.c:5: warning: implicit declaration of function ‘getenv’
nonsense.c:5: warning: assignment makes pointer from integer without a cast
Either adding #include <stdlib.h> or the line you had above, will make the warning go away (even with -Wall -pedantic compiler flags). The compiler will know what to do with the return value - and it figures out the type of the arguments on the fly because it knows the type when it sees it.
And that is the key point: until you tell the compiler the type of the return value of the function it does not know what to do (it will assume int, and make appropriate conversions for the variable you are assigning to - this can be inappropriate. For example, a pointer is often bigger than an int, so information will be lost in the conversion.)
It's a declaration (an old-style one without a prototype, since the argument list is missing) for the function getenv. Aside from being arguably bad style to hide a function declaration alongside the declaration of an object like this, it's bad to omit the prototype and bad not to be using the standard headers (stdlib.h in this case) to get the declarations of standard functions.