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.

AjayR
  • 4,169
  • 4
  • 44
  • 78

8 Answers8

10

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.

M.M
  • 138,810
  • 21
  • 208
  • 365
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
10

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.

Vinicius Kamakura
  • 7,665
  • 1
  • 29
  • 43
  • 5
    It is also, according to the C++ standard, undefined behavior. :) – jalf Jul 14 '11 at 11:38
  • 2
    @jalf This is a C question. – Engineer Jan 03 '15 at 11:47
  • 2
    @NickWiggill fair enough. It is also, according to the C standard, undefined behavior. :) – jalf Jan 03 '15 at 11:59
  • this is not UB under gcc and MS compiler I am pretty sure. It probably is by the C std. – Vinicius Kamakura Jan 05 '15 at 18:47
  • 3
    ^ 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: https://stackoverflow.com/questions/11639947/is-type-punning-through-a-union-unspecified-in-c99-and-has-it-become-specified C++ did **not** inherit this, however. – underscore_d Nov 19 '17 at 20:31
9

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.

Etienne de Martel
  • 34,692
  • 8
  • 91
  • 111
  • 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); ``` – Beezer Dec 06 '20 at 11:56
  • 1
    @Beezer 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. – Etienne de Martel Dec 06 '20 at 21:20
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 */
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
phoxis
  • 60,131
  • 14
  • 81
  • 117
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;
}
  • It wont work as we the char array dont store direct long value it store in bytes, thanks for your answer – AjayR Jul 14 '11 at 02:34
  • 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 me – AjayR Jul 14 '11 at 03:28
-1

This is dirty but it works:

unsigned char myCharArray[8];
// Put some data in myCharArray here...
long long integer = *((long long*) myCharArray);
VincentTellier
  • 558
  • 6
  • 16
-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.

Engineer
  • 8,529
  • 7
  • 65
  • 105
-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

Beezer
  • 1,084
  • 13
  • 18