LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   decimal constant is so large that it is unsigned error? (https://www.linuxquestions.org/questions/linux-newbie-8/decimal-constant-is-so-large-that-it-is-unsigned-error-4175458414/)

Shahid nx 04-17-2013 01:16 AM

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.

lazac 04-17-2013 02:50 AM

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!

millgates 04-17-2013 04:05 AM

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;

Shahid nx 04-17-2013 04:13 AM

Quote:

Originally Posted by millgates (Post 4932993)
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

millgates 04-17-2013 04:41 AM

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.

Shahid nx 04-17-2013 05:06 AM

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

millgates 04-17-2013 05:23 AM

Quote:

Originally Posted by Shahid nx (Post 4933028)
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 (Post 4933028)
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 (Post 4933028)
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.

Shahid nx 04-17-2013 06:37 AM

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

johnsfine 04-17-2013 06:47 AM

Quote:

Originally Posted by Shahid nx (Post 4933084)
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.

Shahid nx 04-17-2013 06:52 AM

Quote:

Originally Posted by johnsfine (Post 4933093)
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?

johnsfine 04-17-2013 07:18 AM

Quote:

Originally Posted by Shahid nx (Post 4933096)
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).

Shahid nx 04-17-2013 07:23 AM

thanks to all..:)

jpollard 04-17-2013 09:03 AM

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.

johnsfine 04-17-2013 09:31 AM

Quote:

Originally Posted by jpollard (Post 4933199)
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.


All times are GMT -5. The time now is 07:48 AM.