LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Slackware (http://www.linuxquestions.org/questions/slackware-14/)
-   -   strtoull, 64bit arithmetic (http://www.linuxquestions.org/questions/slackware-14/strtoull-64bit-arithmetic-4175457432/)

bimboleum 04-08-2013 08:33 PM

strtoull, 64bit arithmetic
 
Hey,
I have a programming problem that is driving me nuts .. and I suspect it has a very simple solution. I am asking here because my system is a Slackware14 64-bit system but if another forum would be more suitable please say so.

I want to perform 64-bit arithmetiuc AND string conversions using unsigned 64 bit entities. My problem is that I appear to be doing 32-bit arithmetic.

I have a test program thus:-

Code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int
main(int argc, char ** argv)
{
    unsigned long long x,y;
    unsigned long long z;
    char *a = "4294967294";
    char *b = "4294967295";
    char *c = "4294967296"; /* this is 4*1024*1024*1024 */
    char *d = "4294967297";
    char *e = "0x0000000101234567";

    x = strtoull(a,NULL,0);
    printf("string %s converts to 0x%16.16X\n",a,x);
    y = strtoull(b,NULL,0);
    printf("string %s converts to 0x%16.16X\n",b,y);
    z = (unsigned long long)x + (unsigned long long)y;
    printf("sum is 0x%16.16X\n",z);
    x = strtoull(c,NULL,0);
    printf("string %s converts to 0x%16.16X\n",c,x);
    x = strtoull(d,NULL,0);
    printf("string %s converts to 0x%16.16X\n",d,x);
    x = strtoull(e,NULL,0);
    printf("string %s converts to 0x%16.16X\n",e,x);
    return(0);
};

This program was compiled using:-
cc -o tt tt.c

and the compiled progam gives results:-

Code:


=>./tt
string 4294967294 converts to 0x00000000FFFFFFFE
string 4294967295 converts to 0x00000000FFFFFFFF
sum is 0x00000000FFFFFFFD
string 4294967296 converts to 0x0000000000000000
string 4294967297 converts to 0x0000000000000001
string 0x0000000101234567 converts to 0x0000000001234567

As you can see, all of the conversions are truncated to 32 bits and the 64-bit addition is handled as a signed 32-bit addition.

Can anyone tell me what I am doing wrong ... please .. this is driving me nuts

cheers
pete

pete hilton
saruman@ruvolo-hilton.org

D1ver 04-08-2013 08:52 PM

I think the problem is your printf formatting codes.

You want to change %16.16X to %16.16LLX, as they're long long hex numbers..

Try compiling with the -Wall switch to increase the error/warning level..

Code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int
main(int argc, char ** argv)
{
    unsigned long long x,y;
    unsigned long long z;
    char *a = "4294967294";
    char *b = "4294967295";
    char *c = "4294967296"; /* this is 4*1024*1024*1024 */
    char *d = "4294967297";
    char *e = "0x0000000101234567";

    x = strtoull(a,NULL,0);
    printf("string %s converts to 0x%16.16llX\n",a,x);
    y = strtoull(b,NULL,0);
    printf("string %s converts to 0x%16.16llX\n",b,y);
    z = (unsigned long long)x + (unsigned long long)y;
    printf("sum is 0x%16.16llX\n",z);
    x = strtoull(c,NULL,0);
    printf("string %s converts to 0x%16.16llX\n",c,x);
    x = strtoull(d,NULL,0);
    printf("string %s converts to 0x%16.16llX\n",d,x);
    x = strtoull(e,NULL,0);
    printf("string %s converts to 0x%16.16llX\n",e,x);
    return(0);
};

Gives

Code:

neil@satellite:~/Documents/Code$ ./mathtest
string 4294967294 converts to 0x00000000FFFFFFFE
string 4294967295 converts to 0x00000000FFFFFFFF
sum is 0x00000001FFFFFFFD
string 4294967296 converts to 0x0000000100000000
string 4294967297 converts to 0x0000000100000001
string 0x0000000101234567 converts to 0x0000000101234567


bimboleum 04-08-2013 10:01 PM

Hey,
You guys are just magic.

I KNEW I was doing something stupid.

Many thanks

cheers
pete

pete hilton

saruman@ruvolo-hilton.org

H_TeXMeX_H 04-09-2013 08:03 AM

There is no real difference between unsigned long and unsigned long long on a 64-bit machine.

Run this and see:
Code:

#include <stdio.h>

int main(int argc, char *argv[])
{
                printf("int=%lu\n",sizeof(int));
                printf("long=%lu\n",sizeof(long));
                printf("ulint=%lu\n",sizeof(unsigned int));
                printf("ulong=%lu\n",sizeof(unsigned long));
                printf("ullong=%lu\n",sizeof(unsigned long long));

        return 0;
}

Code:

int=4
long=8
ulint=4
ulong=8
ullong=8

I wrote a program to convert strings to octal and hex and back, it may interest you:

Code:

// convert between unsigned long, octal, hex
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char * argv[])
{
        // init
        unsigned long ul = 0;
       
        // parse argc
        if (4 != argc)
        {
                printf("Usage:\n%s [u|o|x|X](input type) [u|o|x|X](output type) input\nExample:\n%s u x 123456\n", argv[0], argv[0]);
                exit(1);
        }
       
        // input
        if (!strcmp(argv[1],"u"))
        {
                sscanf(argv[3], "%lu", &ul);
        }
        else if (!strcmp(argv[1],"o"))
        {
                sscanf(argv[3], "%lo", &ul);
        }
        else if (!strcmp(argv[1],"x"))
        {
                sscanf(argv[3], "%lx", &ul);
        }
        else if (!strcmp(argv[1],"X"))
        {
                sscanf(argv[3], "%lX", &ul);
        }
       
        // output
        if (!strcmp(argv[2],"u"))
        {
                printf("%lu\n", ul);
        }
        else if (!strcmp(argv[2],"o"))
        {
                printf("%lo\n", ul);
        }
        else if (!strcmp(argv[2],"x"))
        {
                printf("%lx\n", ul);
        }
        else if (!strcmp(argv[2],"X"))
        {
                printf("%lX\n", ul);
        }
       
        return 0;
}



All times are GMT -5. The time now is 02:59 PM.