strtoul giving unexpected output - c

I am trying to use the strtoul function, but as shown below it is returning an unexpected value (adding ff's in the beginning):
#include <stdio.h>
#include <string.h>
#include <limits.h>
main() {
unsigned long temp ;
char *err;
temp = strtoul("3334444444",&err,10);
if (temp > UINT_MAX) {
printf("%lx %x %x\n",temp,3334444444,UINT_MAX);
}else
printf("%lx %x\n",temp,3334444444);
}
$./a.out
ffffffffc6bf959c c6bf959c ffffffff
The above output corresponds to the if part being true, though I expect the else part to get executed here. Can anyone please explain why strtoul is behaving like this? Why does it return ffffffffc6bf959c rather than just c6bf959c? If I use "333444444" (i.e. just one 4 less) rather than "3334444444" in the above code, then I get the correct output (i.e. 13dff55c 13dff55c) corresponding to the else part.
Note : As pointed by melpomene in his reply below, stdlib.h header file should have been included and that will resolve the issue. Can anyone please let me know what is being done by the program by assuming the incorrect return type (int in this case) during compile time which can't be undone (or atleast it is not getting undone in this case) even after knowing the correct return type (unsigned long in this case) during link time ? In short, i want to know how c6bf959c is getting converted to ffffffffc6bf959c because of prototype not provided.

Compiling your code with gcc with warnings enabled gives:
try.c:5:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main() {
^~~~
try.c:5:1: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
try.c: In function ‘main’:
try.c:8:12: warning: implicit declaration of function ‘strtoul’ [-Wimplicit-function-declaration]
temp = strtoul("3334444444",&err,10);
^~~~~~~
try.c:8:5: warning: nested extern declaration of ‘strtoul’ [-Wnested-externs]
temp = strtoul("3334444444",&err,10);
^~~~
try.c:10:22: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 3 has type ‘long long int’ [-Wformat=]
printf("%lx %x %x\n",temp,3334444444,UINT_MAX);
^
try.c:12:22: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 3 has type ‘long long int’ [-Wformat=]
printf("%lx %x\n",temp,3334444444);
^
The main problem is implicit declaration of function ‘strtoul’, indicating that the function is not declared (and thus assumed to return int) because you forgot to #include <stdlib.h>. Adding the missing #include fixes the value of temp.
But you should also have a look at the warnings reported for printf and fix those.

Related

confused by pointer and local variable in C

according to what i learned about function variables they should not 'live' outside their function scope,thus returning a local function variable should cause an error, i do get compiling warnings that i do expect, but it makes no sense to me because the program do work and i am little confused
i wrote the following program:
int * test(int x) {
int f=x+1;
return f; //- int to pointer conversion,idk why this works
}
int main () {
int x = 10;
printf("%d\n",test(x));
}
I first expected the program to crash because we make conversion from int type to pointer at function return, but apparently the program prints 11 which i did not expect, i know this is really bad to write like this anyways it was just a coincidence i wrote something like this and it worked and I had alot of questions after that
the warnings i expected to get :
Solution.c: In function ‘test’:
Solution.c:10:12: warning: return makes pointer from integer without a cast [-Wint-conversion]
return f;
^
Solution.c: In function ‘main’:
Solution.c:15:14: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("%d\n",test(x));
~^ ~~~~~~~
%ls
can anyone explain how this program works ?
You tell the compiler that function test() should return return a pointer to an integer. You don't. You return a value of an integer.
The compiler says, "You're probably doing unintentional stuff here, just sayin'. I'll cast this integer to a pointer for you."
Then the compiler says, "You want to print the value of an integer here but what you're giving is a pointer. Just sayin'. I'll cast this pointer to an integer for you."

How is the linking done for string functions in C?

I tried to using two different functions from sting.h header file (without including it) strlen() and strtok(). Strlen executed successfully without any error (but some warnings), strtok failed at runtime. Why is it that strlen() function worknig gine but not strtok() if I don't include the header file? I suppose there is something in the linking process that I don't understand. Please clarify for such behavior. However, the program terminates successfully if I print a as '%c' instead of '%s' (strtok returns a garbage value).
CODE:
int main()
{
char string[] = "This is a String";
printf("\nLength of sting is %d\n",strlen(string));
}
WARNINGS:
hello.c: In function ‘main’:
hello.c:4:2: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
hello.c:4:37: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
hello.c:4:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat]
OUTPUT:
$ ./a.out
Length of sting is 16
CODE:
int main()
{
char string[] = "This is a String";
printf("\nLength of sting is %d\n",strlen(string));
char *a = strtok(string," ");
printf("%s",a);
}
WARNINGS:
$ gcc hello.c
hello.c: In function ‘main’:
hello.c:4:2: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
hello.c:4:37: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
hello.c:4:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat]
hello.c:5:12: warning: initialization makes pointer from integer without a cast [enabled by default]
OUTPUT:
$ ./a.out
Length of sting is 16
Segmentation fault (core dumped)
The linking is done implicitly for most of the C standard library. You just have to include the headers of what you use (that's the warnings).
When you don't, your compiler (which is compiling your code as ANSI C) assumes the functions return int, instead of their documented return types. Your program has undefined behavior because of that. Always heed warnings!
You must include the headers string.h and stdio.h.
The first program works because you were lucky enough in that strlen is supposed to return an integer (a size_t to be exact, but it appears on your system the value representation for integers and size_t lets the program slide through).
The second fails because strtok returns a char* but it's assumed an int due to your missing include directives. int and char* are not compatible types, so the "pointer" you get isn't valid.
Sting is a singer, not a C header... Still, the problem is that in C, when you use functions that were not declared, the compiler guesses them to have the types of the arguments you first pass to them and returning an int.
That's the reason why you get all these warnings: several undeclared functions you use don't actually have the deduced signature (although they are not too wrong, and end up working), and the real strtok returns a pointer, not an int (the warning in facts says that you are assigning an int to a pointer without a cast). The crash you are getting most probably comes from the fact that the original pointer is 64 bit, but is truncated to 32 bit when is erroneously considered an int before being assigned to a.
Still, the point to take home is: include headers and don't ever rely on implicit function declaration. It's a dangerous mess that exists only for backward compatibility reasons.

How printf works in case of type mismatch with type specifier?

int main()
{
printf("%c", "\n");
return 0;
}
Here according to type specifier a character is required. But we are passing it const char *. I was hoping that it would give me a warning message in code blocks GNU GCC compiler but it is not giving me any warning and printing the $ character.
why it is not giving any type of warning?
You need to enable that warning.
Compiling your code as test.cpp and adding #include <stdio.h> for printf with the correct warning flag under gcc 4.7.2:
$ gcc -c -Wformat test.cpp
test.cpp: In function 'int main()':
test.cpp:5:18: warning: format '%c' expects argument of type 'int', but argument 2 has type 'const char*' [-Wformat]
With printf() if there is a type mismatch then it leads to undefined behavior.
The format specifier should match with the type which you want to print.
Further the number of arguments should match with the number of format specifiers violating which will also leads to undefined behavior.
Just add -Wall while compiling your code you will get the below error:
warning: format %c expects type int, but argument 2 has type char *
You could see that the code also works with %d, %x, %u format specifiers.
Why it works without any warnings ?
Because you don't have warnings enabled in your CodeBlocks.
Go to settings -> compiler and check
Enable All Common Compiler Warnings [-Wall]
And now you get:
In function 'int main()':
warning: format '%c' expects argument of type 'int', but argument 2 has type 'const char*' [-Wformat=]|
Why it even works ?
With %c, $ is the output in CodeBlocks, X is the output in Visual Studio . So, that sounds like undefined behavior.
Wrong format specifiers in scanf (or) printf
Anyways if you want the first char this way only you could do this:
#include <stdio.h>
int main()
{
printf("%c", *"Hello\n"); // Not asked in Question but still :)
return 0;
}
It prints H by dereferencing the const pointer.

snprintf giving different output

Why is snprintf giving different value in second case. Is it because any integer limit. Can you please explain how snprintf works and why the reason for that negative value
#include <stdio.h>
#include <string.h>
main()
{
char buff[256];
snprintf(buff,256,"%s %d"," value",1879056981);
printf("%s",buff);
}
output:
value 1879056981
#include <stdio.h>
#include <string.h>
main()
{
char buff[256];
snprintf(buff,256,"%s %d"," value",2415927893);
printf("%s",buff);
}
output:
value -1879039403
It's because the integer 2415927893 can't represented by any integer type on your system and you have signed overflow in your program.
The exact type of integer literal depends on how big the number is. C11 defines that an integer literal can be of int or long int or long long int, depending on which one fits first in that order.
6.4.4.1 Integer constants
The type of an integer constant is the first of the corresponding list
in which its value can be represented.
Turn on the compiler warnings.
On my system, gcc warns about it when I compile youre code with:
gcc -std=c11 -Wall -pedantic t.c
t.c:4:1: warning: return type defaults to ‘int’ [enabled by default]
t.c: In function ‘main’:
t.c:9:4: warning: format ‘%d’ expects argument of type ‘int’, but argument 5 has type ‘long long int’ [-Wformat]
t.c:9:4: warning: format ‘%d’ expects argument of type ‘int’, but argument 5 has type ‘long long int’ [-Wformat]
The literal 2415927893 is interpreded as an int. As it is larger than INT_MAX on your machine, you get an overflow.
To avoid this, you may interpret it as an unsigned int:
snprintf(buff,256,"%s %u"," value",2415927893U);
Or as long long:
snprintf(buff,256,"%s %lld"," value",2415927893ll);

Isn't const supposed to be constant?

Check out this code
#include<stdio.h>
int main()
{
const int a=7;
int *p=&a;
(*p)++;
printf("*p=%d\np=%u\na=%d\n&a%u",*p,p,a,&a);
getch();
}
The output you get for this is
*p=8
p=1245064
a=8
&a1245064
How is this possible?? We declared variable a as constant. Doesnt this mean that the location pointed to by a can never be changed during the course of pgm execution??
That's undefined behavior - in your case it is working as you described, but it could just as well crash the program or cause any other problems. In your case const doesn't prevent the compiler from allocating the variable in modifiable memory, so you technically can modify it by obtaining a pointer to that variable and working through the pointer.
Undefined behaviour is not to be relied upon ;-)
Would you really want to use C if it actually prevented that from working? The fact it works that way is very much in the spirit of the language.
Reading your comment "it only gives a warning saying suspicious pointer conversion" it should be clear enough to deduce that you are doing something illegal.
You are assigning to a int * variable a const int * value.
The fact that C hasn't any runtime checkings to prevent you from modifying that memory address doesn't imply that it's allowed! (and in fact, the static type system checking is telling you that).
If yours doesn't detect this automatically, just get yourself a decent compiler. E.g clang gives me 4 problems with your code:
clang -c -o test-const.o test-const.c
test-const.c:17:7: warning: initializing 'int const *' discards qualifiers, expected 'int *' [-pedantic]
int *p=&a;
^ ~~
test-const.c:19:20: warning: conversion specifies type 'unsigned int' but the argument has type 'int *' [-Wformat]
printf("*p=%d\np=%u\na=%d\n&a%u",*p,p,a,&a);
~^ ~
test-const.c:19:32: warning: conversion specifies type 'unsigned int' but the argument has type 'int const *' [-Wformat]
printf("*p=%d\np=%u\na=%d\n&a%u",*p,p,a,&a);
~^ ~~
test-const.c:20:2: warning: implicit declaration of function 'getch' is invalid in C99 [-Wimplicit-function-declaration]
getch();
^
4 diagnostics generated.
These are all serious problems.

Resources