LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 04-17-2013, 01:16 AM   #1
Shahid nx
Member
 
Registered: Jan 2012
Posts: 46

Rep: Reputation: Disabled
decimal constant is so large that it is unsigned error?


Hi all,
Plz help me fast..
i want to store 11601508835565898551 data into any of integer variable ,since this value is looking large so i have used unsigned long long type but still it is giving warning "as decimal constant is so large that it is unsigned". And after that i also need to store this value in array of char using sprintf().

Please help me how can i copy this large value into integer in gcc.
 
Old 04-17-2013, 02:50 AM   #2
lazac
LQ Newbie
 
Registered: Mar 2010
Location: Budapest
Distribution: Debian
Posts: 8

Rep: Reputation: 0
Maybe "guint64" type of glib library could do that. Its maximum value (G_MAXUINT64) is 18446744073709551615. But you need a 64-bit platform for using it!
 
Old 04-17-2013, 04:05 AM   #3
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
What is the language? C?
The warning here does not complain about the variable you store the number in. unsigned long long (at least on i386/x86_64 gcc linux) is large enough to hold the number. The problem is with the integer literal. When you declare a decimal integral literal in C, the compiler treats it as the first integral type that can hold the value, checking in the following order: int, long int, long long int. But your number is so large that it can not fit the signed long long type. To get rid of the warning, define the literal explicitly as unsigned:

Code:
unsigned long long i = 11601508835565898551u;
 
Old 04-17-2013, 04:13 AM   #4
Shahid nx
Member
 
Registered: Jan 2012
Posts: 46

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by millgates View Post
What is the language? C?
The warning here does not complain about the variable you store the number in. unsigned long long (at least on i386/x86_64 gcc linux) is large enough to hold the number. The problem is with the integer literal. When you declare a decimal integral literal in C, the compiler treats it as the first integral type that can hold the value, checking in the following order: int, long int, long long int. But your number is so large that it can not fit the signed long long type. To get rid of the warning, define the literal explicitly as unsigned:

Code:
unsigned long long i = 11601508835565898551u;


Im writing code in C only. When i tried this warning goes off but but while executing it is giving error.
I have put wnat i wanted to do in simple program.. I just want this program to execute.
Code:
#include <stdio.h>

int main()
{
        unsigned long long Data = 11601508835565898551u;
        unsigned char CharData[8]="";
        printf ("Value :%llu\n", Data);
        sprintf(CharData,"%llu",Data);
        printf ("CharDAte %s",CharData);
        return 0;
}
Now output i m getting is
Value :11601508835565898551
Illegal instruction
 
Old 04-17-2013, 04:41 AM   #5
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
Code:
unsigned char CharData[8]="";
sprintf(CharData,"%llu",Data);
Why 8? How many characters do you need to represent the number 11601508835565898551?
Also, don't forget about the terminating 0.
 
Old 04-17-2013, 05:06 AM   #6
Shahid nx
Member
 
Registered: Jan 2012
Posts: 46

Original Poster
Rep: Reputation: Disabled
Actually i thought 8 byte in enough to store this value. Bt when i change size of char aaraa that Illegal instruction has gone but still i m not getting the expected answer. Ultimately i also need to convert that value to integer..

This is the modified code ,after atoll() i m expecting answer as initial value
11601508835565898551
Code:
 #include <stdio.h>

int main()
{
        unsigned long long Data = 11601508835565898551; //11601508835565898551
        unsigned char CharData[50]="";
        printf ("Value :%llu\n", Data);
        sprintf(CharData,"%llu",Data);
        CharData[strlen(CharData)]='\0';
        printf ("CharData1 %s\n",CharData);
        printf ("CharDate2 %llu\n",atoll(CharData));

return 0;
}
Out[put i m getting is
Value :11601508835565898551
CharData1 11601508835565898551
CharDate2 9977174359631986687
 
Old 04-17-2013, 05:23 AM   #7
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
Quote:
Originally Posted by Shahid nx View Post
Actually i thought 8 byte in enough to store this value.
No, the number has 20 digits, so you need 20 + 1 = 21 bytes.

Quote:
Originally Posted by Shahid nx View Post
Bt when i change size of char aaraa that Illegal instruction has gone but still i m not getting the expected answer.
What are you getting?


Quote:
Originally Posted by Shahid nx View Post
This is the modified code ,after atoll() i m expecting answer as initial value 11601508835565898551
You're converting the number to signed long long. That's not large enough to hold your number. You need unsigned long long.
If you use C99, strtoull() might be better suited for the task.

Code:
        CharData[strlen(CharData)]='\0';
This is actually not necessary. sprintf() does that for you.
 
Old 04-17-2013, 06:37 AM   #8
Shahid nx
Member
 
Registered: Jan 2012
Posts: 46

Original Poster
Rep: Reputation: Disabled
Thank You very much.... Now my program is working fine...
Now just for understanding i have one query. As u have told " the number has 20 digits, so you need 20 + 1 = 21 bytes." But i believe since unsigned long long is of 8 byte so this 8+1(for NULL) is enough to hold. And my code is also working fine array size 9.
Code:
 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        unsigned long long Data = 11601508835565898551u;
        unsigned char CharData[9]="";
        printf ("Value  :%llu\n", Data);
        sprintf(CharData,"%llu",Data);
        printf ("CharData1 %s\n",CharData);
        printf ("CharData2 %llu\n",strtoull(CharData,NULL,0));

return 0;
}
OutPut:
Value :11601508835565898551
CharData1 11601508835565898551
CharData2 11601508835565898551
 
Old 04-17-2013, 06:47 AM   #9
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by Shahid nx View Post
my code is also working fine array size 9.
Lack of a symptom never proves lack of a bug.
Millgates is correct about the required array size.

Quote:
since unsigned long long is of 8 byte so this 8+1(for NULL) is enough to hold.
An unsigned long long is 8 bytes. But CharData is not an unsigned long long. When you convert a number into a series of digits the required storage typically changes. In this case, storing the number as a series of digits requires 21 bytes.

At run time, your program uses 21 bytes of CharData. Since you only allocated 9 bytes, it uses those 9 bytes plus the following 12 bytes. The consequences of using those following 12 bytes depend on what use the compiler assigned to those 12 bytes. The lack of problems you currently see is just an accident caused by the simplicity of your total program combined with arbitrary stack layout choices made by the compiler.

Last edited by johnsfine; 04-17-2013 at 06:55 AM.
 
Old 04-17-2013, 06:52 AM   #10
Shahid nx
Member
 
Registered: Jan 2012
Posts: 46

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by johnsfine View Post
Lack of a symptom never proves lack of a bug.
Millgates is correct about the required array size.
Ya i also agree to it..Logically that is true ,, But practically when i executes this program it is not giving any error. why?
 
Old 04-17-2013, 07:18 AM   #11
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by Shahid nx View Post
Ya i also agree to it..Logically that is true ,, But practically when i executes this program it is not giving any error. why?
That depends on many arbitrary decisions made by the compiler. If I saw the asm code generated by the compiler, I would know exactly why your bug had no symptoms. But I don't know your compiler version, architecture or settings, so compiling it myself is unlikely to give the same asm code.

An example with a hypothetical x86 compiler (this is not a correct description for any compiler settings you are likely to be using, but may be more informative regarding the kinds of accidents involved than a true version would be).

The top of the stack frame is the saved ebp and eip of the caller.
The compiler might decide on a stack layout in which your 8 byte Data is right below that and CharData right below that and might decide to align CharData on a four byte boundary.

If CharData is 9 bytes long, the next 12 bytes are 3 bytes of alignment waste followed by all of Data, followed by the low byte of the saved ebp. So your bug destroys all of Data right after using it for the last time, so you don't notice that aspect, and it clears the low 8 bits of the caller's ebp. The low 4 bits were clear anyway, so there was one chance in 16 that the whole low byte of the saved ebp was already clear, so clearing it again is symptom free.

Under the same compiler rules, if CharData were 8 bytes long, there are no longer 3 bytes of alignment waste, so the next 13 bytes are all of Data, and all of the saved ebp (so if the program got as far as the caller of main using ebp, that would crash) but also includes the low byte of the saved eip, which we will assume was not 0. So when main() returns, it doesn't return to the right place, but to the middle of a multi-byte instruction somewhere earlier in the code that called it. That middle of a multi-byte instruction, misinterpreted as the beginning of an instruction, happens to not decode as any legal instruction, causing an illegal instruction fault (which is quite rare for this kind of bug. Usually you get a seg fault, not an illegal instruction, but once you are clobbering parts of your stack frame results are generally unpredictable).

Last edited by johnsfine; 04-17-2013 at 07:20 AM.
 
Old 04-17-2013, 07:23 AM   #12
Shahid nx
Member
 
Registered: Jan 2012
Posts: 46

Original Poster
Rep: Reputation: Disabled
thanks to all..
 
Old 04-17-2013, 09:03 AM   #13
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
As a brief follow up...

Instead of using sprintf, use snprintf as it takes the size of the buffer as an additional parameter. That way an overflow will not happen, and you will get a more suitable error message.

If you want a bit of fun, try rearranging the order of declaration...

If you put CharData first you might find that the value gets wiped out.

Last edited by jpollard; 04-17-2013 at 09:07 AM.
 
Old 04-17-2013, 09:31 AM   #14
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by jpollard View Post
If you want a bit of fun, try rearranging the order of declaration...

If you put CharData first you might find that the value gets wiped out.
You are making a very strange assumption about the way gcc works. Did you try that yourself? I think you would be surprised.

I tried in x86_64, unoptimized, with gcc 3.4.6
The local variables Data and CharData are allocated in reverse sequence to their declaration. So if Data is declared first, it is allocated last and gets clobbered by overrun from CharData. But when I reverse the sequence and declare Data second, it is allocated below CharData and is not clobbered.

Many details would be different in a more current version of gcc, but (based on the asm code from similar bugs others have posted here) I think that detail of allocation sequence is consistent across many versions of gcc.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
why omit unsigned int in unsuffixed decimal integer constant? password636 Programming 1 11-15-2011 11:00 PM
[SOLVED] error: large integer implicitly truncated to unsigned type sajnanazeer Programming 4 08-19-2011 02:32 AM
Format large numbers with commas at every thousandth decimal spot helpmhost Linux - General 8 10-01-2007 11:54 AM
rounding a large double to 2 decimal places linuxmandrake Programming 2 03-17-2006 03:31 PM
Integer Constant is too large B00H Linux - Software 7 11-01-2005 09:39 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 01:04 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration