NO

Author Topic: [SOLVED-NotABugByIDE] May be a bug with long long int and a problem with scanf_s  (Read 3616 times)

LaVanTien

  • Guest
First, I wrote a program to calculate factorial of a natural number, I know the range of 64-bit integer can handle upto 20!, but the problem is when I run my program under Pelles C it gets wrong answer (very very wrong) for 20!, but others are well result (just 20! doesn't).

------------------------------------------------------------------------------------------------------------------------------
I thaught I had a mistake in my code, but not, my code work very perfect on Visual Studio 2013, the program give exactly result for 20!.

------------------------------------------------------------------------------------------------------------------------------
Second, when I use scanf_s function, I get an error although I've already included stdio.h:

------------------------------------------------------------------------------------------------------------------------------
If two of these really are a bugs/errors/misstakes/... I hope two of these will be fixed.

If not, can someone tells me how to find reference to these points or suggest me how to fix this, thanks very much!
------------------------------------------------------------------------------------------------------------------------------
Here is my code:
Code: [Select]
#include<stdio.h>
#include<windows.h> //Windows enviroment

long long int table[20]; //Reuse previous values to improve performance

long long int fac(int);
void cls(HANDLE hConsole); //Clear screen function

int main(void) {
int n;
HANDLE hStdout;
hStdout=GetStdHandle(STD_OUTPUT_HANDLE);
for (;;) {
cls(hStdout);
fputs("n = ",stdout);
scanf_s("%d",&n); //C11
if (n<0||n>20) { //64-bit integer will only work with factorial of [0..20]
puts("The program has stopped working.");
while ((n=getchar())!=10);
getchar();
break;
}
if (table[n]==0)
table[n]=fac(n);
printf("%d! = %lld\n",n,table[n]);
while ((n=getchar())!=10);
getchar();
}
return 0;
}

long long int fac(int x) {
if (x<2)
return 1;
int i;
long long int t;
t=x;
for (i=2;i<x;i++)
t*=i;
return t;
}
void cls(HANDLE hConsole) {
COORD coordScreen={0,0};
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
if (!GetConsoleScreenBufferInfo(hConsole,&csbi)) {
return;
}
dwConSize=csbi.dwSize.X*csbi.dwSize.Y;
if (!FillConsoleOutputCharacter(hConsole,(TCHAR)' ',dwConSize,coordScreen,&cCharsWritten)) {
return;
}
if(!GetConsoleScreenBufferInfo(hConsole,&csbi)) {
return;
}
if (!FillConsoleOutputAttribute(hConsole,csbi.wAttributes,dwConSize,coordScreen,&cCharsWritten)) {
return;
}
SetConsoleCursorPosition(hConsole,coordScreen);
}
------------------------------------------------------------------------------------------------------------------------------
Ps:  I really love Pelles C IDE and always do C projects on it. I find that the code generate by Pelles C fast at least twice if compare with VS, or 1.5 time faster if compare with Code::Blocks (of course on C mode).
« Last Edit: April 17, 2015, 12:03:35 PM by LaVanTien »

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: May be a bug with long long int and a problem with scanf_s
« Reply #1 on: April 17, 2015, 10:47:53 AM »
for scanf_s use #define __STDC_WANT_LIB_EXT1__ 1
PellesC have _clrscr(); in <conio.h>
Code: [Select]
#include<stdio.h>

long long int fac(int x) {
if (x<2)
return 1;
int i;
long long int t;
t=x;
for (i=2;i<x;i++)
t*=i;
return t;
}

int main(void) {
long long x = fac(20);
printf("%lld\n", x);
return 0;
}
output
Code: [Select]
2432902008176640000
Press any key to continue...
« Last Edit: April 17, 2015, 10:54:37 AM by TimoVJL »
May the source be with you

Snowman

  • Guest
Re: May be a bug with long long int and a problem with scanf_s
« Reply #2 on: April 17, 2015, 10:57:42 AM »
There is no problem with long long int.

Your bug is caused by the fact that you go out of bounds when using your long long int table[] array.
In C indexing starts from 0:

Code: [Select]
int arr[5];

arr[0] = 0; // OK
arr[1] = 0; // OK
arr[2] = 0; // OK
arr[3] = 0; // OK
arr[4] = 0; // OK
arr[5] = 0; // NOT OK, out of bounds!
arr[6] = 0; // NOT OK, out of bounds!

In your case, you save the result for factorial of 20 in table[20] which is not a valid position and may be overwritten (used by other variables). If your program is compiled by Visual Studio, you are lucky and the program doesn't touch that area which is why it seems like everything works fine.

Also a suggestion: why use long long int instead of UINT64 from windows.h or uint64_t from stdint.h?

https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx
http://en.cppreference.com/w/c/types/integer


LaVanTien

  • Guest
Re: May be a bug with long long int and a problem with scanf_s
« Reply #3 on: April 17, 2015, 11:57:06 AM »
Quote
Your bug is caused by the fact that you go out of bounds when using your long long int table[] array.

Thanks you Snowman, I have just realized how stupid I am.

And now the problem gone out
Code: [Select]
long long int table[21];  8)

Quote
Also a suggestion: why use long long int instead of UINT64 from windows.h or uint64_t from stdint.h?

I used to use 'long long int' when need a 64-bit integer, because on my machine 'long long int' will exactly be 64 bit. I didn't know the differents between these 64-bit integer type, nor know about their impact to performance. I always use 'long long int' because of my habit.

Quote
for scanf_s use #define __STDC_WANT_LIB_EXT1__ 1

TimoVJL, It still doesn't work  :(

------------------------------------------------------------------------------------------------------------------------------

Quote
PellesC have _clrscr(); in <conio.h>
When I'm begin learning C, I always be told that I need to avoid conio.h, I know a part of this advice is about conio.h is not portable, nor standard, but I really don't know if I using it, then can I get any impact to performance? I really need performance, so I try to improve it everytime I can  ::)

[EDIT] Now it work like a charm LOL, thanks you TimoVJL
Code: [Select]
#define __STDC_WANT_LIB_EXT1__ 1
#include<stdio.h>
#include<windows.h> //Windows enviroment
« Last Edit: April 17, 2015, 12:00:39 PM by LaVanTien »