Converting Char array to Long in C
Asked Answered
C

9

6

This question may looks silly, but please guide me I have a function to convert long data to char array

void ConvertLongToChar(char *pSrc, char *pDest)
{
    pDest[0] = pSrc[0];
    pDest[1] = pSrc[1];
    pDest[2] = pSrc[2];
    pDest[3] = pSrc[3];
}

And I call the above function like this

long lTemp = (long) (fRxPower * 1000);
ConvertLongToChar ((char *)&lTemp, pBuffer);

Which works fine. I need a similar function to reverse the procedure. Convert char array to long. I cannot use atol or similar functions.

Contraception answered 14/7, 2011 at 1:20 Comment(0)
L
11

Leaving the burden of matching the endianness with your other function to you, here's one way:

unsigned long int l = pdest[0] | (pdest[1] << 8) | (pdest[2] << 16) | (pdest[3] << 24);

Just to be safe, here's the corresponding other direction:

unsigned char pdest[4];
unsigned long int l;
pdest[0] = l         & 0xFF;
pdest[1] = (l >>  8) & 0xFF;
pdest[2] = (l >> 16) & 0xFF;
pdest[3] = (l >> 24) & 0xFF;

Going from char[4] to long and back is entirely reversible; going from long to char[4] and back is reversible for values up to 2^32-1.

Note that all this is only well-defined for unsigned types.

(My example is little endian if you read pdest from left to right.)

Addendum: I'm also assuming that CHAR_BIT == 8. In general, substitute multiples of 8 by multiples of CHAR_BIT in the code.

Lactation answered 14/7, 2011 at 1:23 Comment(0)
I
11

You can do:

union {
 unsigned char c[4];
 long l;
} conv;

conv.l = 0xABC;

and access c[0] c[1] c[2] c[3]. This is good as it wastes no memory and is very fast because there is no shifting or any assignment besides the initial one and it works both ways.

Innuendo answered 14/7, 2011 at 1:37 Comment(5)
It is also, according to the C++ standard, undefined behavior. :)Bede
@jalf This is a C question.Captain
@NickWiggill fair enough. It is also, according to the C standard, undefined behavior. :)Bede
this is not UB under gcc and MS compiler I am pretty sure. It probably is by the C std.Innuendo
^ What compilers do isn't actually informative at all about what the Standard says, though you happened to be correct anyway. @jalf No, C made type-punning via a union well-specified in C99 onwards: #11640447 C++ did not inherit this, however.Punk
A
10

A simple way would be to use memcpy:

char * buffer = ...;
long l;
memcpy(&l, buff, sizeof(long));

That does not take endianness into account, however, so beware if you have to share data between multiple computers.

Allnight answered 14/7, 2011 at 1:22 Comment(2)
I tried your example but it did not work for me. What did, was something very similar: char* vIn = "0"; long vOut = strtol(vIn,NULL,10); Brocklin
@Brocklin That does a very different thing: your method parses text into a number, while mine interprets the bytes of a buffer as a long. These are different problems.Allnight
S
4

If you mean to treat sizeof (long) bytes memory as a single long, then you should do the below:

char char_arr[sizeof(long)];
long l;

memcpy (&l, char_arr, sizeof (long));

This thing can be done by pasting each bytes of the long using bit shifting ans pasting, like below.

l = 0;
l |= (char_arr[0]);
l |= (char_arr[1] << 8);
l |= (char_arr[2] << 16);
l |= (char_arr[3] << 24);

If you mean to convert "1234\0" string into 1234L then you should

l = strtol (char_arr, NULL, 10); /* to interpret the base as decimal */
Sarabia answered 14/7, 2011 at 1:26 Comment(0)
S
0

Does this work:

#include<stdio.h>

long ConvertCharToLong(char *pSrc) {
    int i=1;
    long result = (int)pSrc[0] - '0';
    while(i<strlen(pSrc)){
         result = result * 10 + ((int)pSrc[i] - '0');
         ++i;
    }
    return result;
}


int main() {
    char* str = "34878";
    printf("The answer is %d",ConvertCharToLong(str));
    return 0;
}
Suffocate answered 14/7, 2011 at 1:33 Comment(2)
It wont work as we the char array dont store direct long value it store in bytes, thanks for your answerContraception
you are correct with your example. In My case it is not the long data but bytes it is storing, so this solution not works for meContraception
M
0
unsigned long long convert_achar_to_unsigned_long_long(char *src) {
  unsigned long long ret = 0;
  char digit[2];
  digit[1] = '\0';
  byte n = 0;
  while(src[n] != '\0') {    
    digit[0] = src[n];
    if(n!=0) {
      ret *= 10;
    }  
    ret += atoi(digit);
    n++;
  }
  return ret;
}
Mo answered 8/9, 2023 at 8:54 Comment(1)
This implementation is irrelevant for the OP's question and rather inefficient for its purpose: check for a digit and use src[n] - '0' instead of atoi(digit).Chemosphere
E
-1

This is dirty but it works:

unsigned char myCharArray[8];
// Put some data in myCharArray here...
long long integer = *((long long*) myCharArray);
Eran answered 20/3, 2014 at 9:34 Comment(1)
and this is wrong, aliasing error and possible undefined behaviour from wrong alignmentBookman
C
-1
char charArray[8]; //ideally, zero initialise
unsigned long long int combined = *(unsigned long long int *) &charArray[0];

Be wary of strings that are null terminated, as you will end up copying any bytes beyond the null terminator into combined; thus in the above assignment, charArray needs to be fully zero-initialised for a "clean" conversion.

Captain answered 3/1, 2015 at 16:14 Comment(1)
and this is wrong, aliasing error and possible undefined behaviour from wrong alignmentBookman
B
-1

Just found this having tried more than one of the above to no avail :=( :

    char * vIn = "0";
    long vOut = strtol(vIn,NULL,10);

Worked perfectly for me. To give credit where it is due, this is where I found it: https://www.convertdatatypes.com/Convert-char-Array-to-long-in-C.html

Brocklin answered 6/12, 2020 at 12:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.