simple bit manipulation fails - c

I am learning bit manipulation in C and I have written a simple program. However the program fails. Can someone please look into this code?
Basically I want to extract and reassemble a 4 byte 'long' variable to its induvidual bytes and vice versa. Here is my code:
printf("sizeof char= %d\n", sizeof(char));
printf("sizeof unsigned char= %d\n", sizeof(unsigned char));
printf("sizeof int= %d\n", sizeof(int));
printf("sizeof long= %d\n", sizeof(long));
printf("sizeof unsigned long long= %d\n", sizeof(unsigned long long));
long val = 2;
int k = 0;
size_t len = sizeof(val);
printf("val = %ld\n", val);
printf("len = %d\n", len);
char *ptr;
ptr = (char *)malloc(sizeof(len));
//converting 'val' to char array
//val = b3b2b1b0 //where 'b is 1 byte. Since 'long' is made of 4 bytes, and char is 1 byte, extracting byte by byte of long into char
//do{
//val++;
for(k = 0; k<len; k++){
ptr[k] = ((val >> (k*len)) && 0xFF);
printf("ptr[%d] = %02X\n", k,ptr[k]);
}
//}while(val < 12);
//reassembling the bytes from char and converting them to long
long xx = 0;
int m = 0;
for(m = 0; m< len; m++){
xx = xx |(ptr[m]<<(m*8));
}
printf("xx= %ld\n", xx);
Why don't I see xx returning 2?? Also, irrespective of the value of 'val', the ptr[0] seems to store 1 :(
Please help
Thanks in advance

ptr[k] = ((val >> (k*len)) && 0xFF);
Should be
ptr[k] = ((val >> (k*8)) & 0xFF);
&& is used in conditional statements and & for bitwise and.
Also as you're splitting the value up into chars, each iteration of the loop you want to shift with as many bits as are in a byte. This is almost always 8 but can be something else. The header file limits.h has the info about that.

A few things I notice:
You're using the boolean && operator instead of bitwise &
You're shifting by "k*len" instead of "k*8"
You're allocating an array with "sizeof(len)", instead of just "len"
You're using "char" instead of "unsigned char". This will make the "(ptr[m]<<(m*8))" expression sometimes give you a negative number.
So a fixed version of your code would be:
printf("sizeof char= %d\n", sizeof(char));
printf("sizeof unsigned char= %d\n", sizeof(unsigned char));
printf("sizeof int= %d\n", sizeof(int));
printf("sizeof long= %d\n", sizeof(long));
printf("sizeof unsigned long long= %d\n", sizeof(unsigned long long));
long val = 2;
int k = 0;
size_t len = sizeof(val);
printf("val = %ld\n", val);
printf("len = %d\n", len);
unsigned char *ptr;
ptr = (unsigned char *)malloc(len);
//converting 'val' to char array
//val = b3b2b1b0 //where 'b is 1 byte. Since 'long' is made of 4 bytes, and char is 1 byte, extracting byte by byte of long into char
//do{
//val++;
for(k = 0; k<len; k++){
ptr[k] = ((val >> (k*8)) & 0xFF);
printf("ptr[%d] = %02X\n", k,ptr[k]);
}
//}while(val < 12);
//reassembling the bytes from char and converting them to long
long xx = 0;
int m = 0;
for(m = 0; m< len; m++){
xx = xx |(ptr[m]<< m*8);
}
printf("xx= %ld\n", xx);
Also, in the future, questions like this would be better suited to https://codereview.stackexchange.com/

As others have by now mentioned, I'm not sure if ptr[k] = ((val >> (k*len)) && 0xFF); does what you want it to. The && operator is a boolean operator. If (value >> (k*len)) is some non-zero value, and 0xFF is some non-zero value, then the value stored into ptr[k] will be one. That's the way boolean operators work. Perhaps you meant to use & instead of &&.
Additionally, you've chosen to use shift operators, which is appropriate for unsigned types, but has a variety of non-portable aspects for signed types. xx = xx |(ptr[m]<<(m*8)); potentially invokes undefined behaviour, for example, because it looks like it could result in signed integer overflow.
In C, sizeof (char) is always 1, because the sizeof operator tells you how many chars are used to represent a type. eg. sizeof (int) tells you how many chars are used to represent ints. It's CHAR_BIT that changes. Thus, your code shouldn't rely upon the sizeof a type.
In fact, if you want your code to be portable, then you shouldn't be expecting to be able to store values greater than 32767 or less than -32767 in an int, for example. This is regardless of size, because padding bits might exist. To summarise: the sizeof a type doesn't necessarily reflect the set of values it can store!
Choose the types of your variables for their application, portably. If your application doesn't need values beyond that range, then int will do fine. Otherwise, you might want to think about using a long int, which can store values between (and including) -2147483647 and 2147483647, portably. If you need values beyond that, use a long long int, which will give you the guaranteed range consisting of at least the values between -9223372036854775807 and 9223372036854775807. Anything beyond that probably deserves a multi-precision arithmetic library such as GMP.
When you don't expect to use negative values, you should use unsigned types.
With consideration given to your portable choice of integer type, it now makes sense that you can devise a portable way to write those integers into files, and read those integers from files. You'll want to extract the sign and absolute value into unsigned int:
unsigned int sign = val < 0; /* conventionally 1 for negative, 0 for positive */
unsigned int abs_val = val;
if (val < 0) { abs_val = -abs_val; }
... and then construct an array of 8-bit chunks of abs_val and sign, merged together. We've already decided using portable decision-making that our int can only store 16 bits, because we're only ever storing values between -32767 and 32767 in it. As a result, there is no need for a loop, or bitwise shifts. We can use multiplication to move our sign bit, and division/modulo to reduce our absolute value. Consider that the sign conventionally goes with the most significant bit, which is either at the start (big endian) or the end (little endian) of our array.
unsigned char big_endian[] = { sign * 0x80 + abs_val / 0x100,
abs_value % 0x100 };
unsigned char lil_endian[] = { abs_value % 0x100,
sign * 0x80 + abs_val / 0x100 };
To reverse this process, we perform the opposite operations in reverse of each other (that is, using division and modulo in place of multiplication, multiplication in place of division and addition, extract the sign bit and reform the value):
unsigned int big_endian_sign = array[0] / 0x80;
int big_endian_val = big_endian_sign
? -((array[0] % 0x80) * 0x100 + array[1])
: ((array[0] % 0x80) * 0x100 + array[1]);
unsigned int lil_endian_sign = array[1] / 0x80;
int lil_endian_val = lil_endian_sign
? -((array[1] % 0x80) * 0x100 + array[0])
: ((array[1] % 0x80) * 0x100 + array[0]);
The code gets a little more complex for long, and it becomes worthwhile to use binary operators. The extraction of sign and absolute value remains essentially the same, with the only changes being the type of the variables. We still don't need loops, because we made a decision that we only care about values representable portably. Here's how I'd convert from a long val to an unsigned char[4]:
unsigned long sign = val < 0; /* conventionally 1 for negative, 0 for positive */
unsigned long abs_val = val;
if (val < 0) { abs_val = -abs_val; }
unsigned char big_endian[] = { (sign << 7) | ((abs_val >> 24) & 0xFF),
(abs_val >> 16) & 0xFF,
(abs_val >> 8) & 0xFF,
abs_val & 0xFF };
unsigned char lil_endian[] = { abs_val & 0xFF,
(abs_val >> 8) & 0xFF,
(abs_val >> 16) & 0xFF,
(sign << 7) | ((abs_val >> 24) & 0xFF) };
... and here's how I'd convert back to the signed value:
unsigned int big_endian_sign = array[0] >> 7;
long big_endian_val = big_endian_sign
? -((array[0] & 0x7F) << 24) + (array[1] << 16) + (array[2] << 8) + array[3]
: ((array[0] & 0x7F) << 24) + (array[1] << 16) + (array[2] << 8) + array[3];
unsigned int lil_endian_sign = array[3] >> 7;
long lil_endian_val = lil_endian_sign
? -((array[3] & 0x7F) << 24) + (array[2] << 16) + (array[1] << 8) + array[0]
: ((array[3] & 0x7F) << 24) + (array[2] << 16) + (array[1] << 8) + array[0];
I'll leave you to devise a scheme for unsigned and long long types... and open up the floor for comments:

Related

Converting 8 byte char array into long

How do we convert 8 byte char array into long since << does not work for type long?
#define word_size 8
long num = 0;
char a[word_size] = "\x88\x99\xaa\x0bb\xcc\xdd\xee\xff";
for (i=0; i < word_size;i++) {
a[(word_size-1) - i] |= (num << (8*(word_size - i - 1))) & 0xFF;
}
printf("%lx\n", num);
The following code is more efficient:
unsigned char[word_size] = ...;
int64_t num = 0;
for ( int i = 0 ; i < sizeof(a) ; i++ )
num = (num << 8) | a[i];
This assumes big endian (highest order byte first) ordering of the bytes in the array. For little endian (as you appear to use) just process it top-down:
for ( int i = sizeof(a) ; --i >= 0 ; )
Note: whether char is signed or unsigned is implementation-dependent, so nail it down to be unsigned, otherwise the logical-or will not work. Better use uint8_t; that is defined to be 8 bits, while char is not.
Note: You should use all-uppercase for constants: WORD_SIZE instead of word_size. That is a commonly accepted standard (quite the only about case for identifiers in C).

C: Computing a series of bits spanned over several bytes

I have got a unsigned char array of bytes like:
unsigned char[20] = {0xff, 0x1a, 0x70, 0xa9, ...}
I now want to perform computations over x consecutive bits of this array (with x > 8; e.g x = 15). In particular, I want to perform majortiy voting on every 15 bits, which returns a single bit. Subsequently, the returned single bits shall be converted to an unsigned char byte again.
I already implemented the majorityVoting algorithm. I also implemented a naive algorithm for the whole problem, which works this way:
Convert the byte array into a bit array (also unsigned char[] holding zeros and ones)
Loop over the bit array and pass every series of x bits to the majority voting function
Collect the majority vote results also in a bit array (unsigned char[])
Loop over this bit array and use bitwise operations to construct bytes from every series of 8 bits.
To me this seems intuitive but cumbersome at the same time.
Do you see any possibilities for optimization or could you even give a slicker algorithm?
Best regards,
P.
You could get the next bit of the array with a function like that
int nextBit( unsigned char [] arr, int *pByte, size_t nBytes, int *pBit )
{
int result;
if( *pByte >= nBytes ) {
// Padding, neccessary if nBytes % 15 != 0
return 0;
} else {
result = ( arr[*pByte] >> (*pBit) ) & 0x1;
if( *pBit == 7 ) {
(*pByte)++;
*pBit = 0;
} else {
(*pBit)++;
}
return result;
}
}
and loop:
int byte=0, bit=0;
int result;
int i;
while( byte < sizeof( arr ) ) {
for( i=0; i<15; i++ ) {
result = nextBit( arr, &byte, sizeof( arr ), &bit );
// do the majority voting
}
}
A quite similar function can be created to directly create an array of the majority bits
You could bitshift every byte into 17 bits (and store them in 17 bytes).
uint8_t bits[17];
bits[0] = !!(bytes[0] & 128);
bits[1] = !!(bytes[0] & 64);
bits[2] = !!(bytes[0] & 32);
bits[3] = !!(bytes[0] & 16);
bits[4] = !!(bytes[0] & 8);
bits[5] = !!(bytes[0] & 4);
bits[6] = !!(bytes[0] & 2);
bits[7] = !!(bytes[0] & 1);
bits[8] = !!(bytes[1] & 128);
bits[9] = !!(bytes[1] & 64);
bits[10] = !!(bytes[1] & 32);
bits[11] = !!(bytes[1] & 16);
bits[12] = !!(bytes[1] & 8);
bits[13] = !!(bytes[1] & 4);
bits[14] = !!(bytes[1] & 2);
bits[15] = !!(bytes[1] & 1);
bits[16] = !!(bytes[2] & 128);
I'm not sure about what you want to do with those bits, but you can also consider storing the bits in a 32 bit integer:
uint32_t chunk = (bytes[0] << 9) | (bytes[1] << 1) | (bytes[2] & 1);

How to encode a numeric value as bytes

I need to be able to be able to send a numeric value to a remote socket server and so I need to encode possible numbers as bytes.
The numbers are up to 64 bit, ie requiring up to 8 bytes. The very first byte is the type, and it is always a number under 255 so fits in 1 byte.
For example, if the number was 8 and the type was a 32 bit unsigned integer then the type would be 7 which would be copied to the first (leftmost) byte and then the next 4 bytes would be encoded with the actual number (8 in this case).
So in terms of bytes:
byte1: 7
byte2: 0
byte3: 0
byte4: 0
byte5: 8
I hope this is making sense.
Does this code to perform this encoding look like a reasonable approach?
int type = 7;
uint32_t number = 8;
unsigned char* msg7 = (unsigned char*)malloc(5);
unsigned char* p = msg7;
*p++ = type;
for (int i = sizeof(uint32_t) - 1; i >= 0; --i)
*p++ = number & 0xFF << (i * 8);
You'll want to explicitly cast type to avoid a warning:
*p++ = (unsigned char) type;
You want to encode the number with most significant byte first, but you're shifting in the wrong direction. The loop should be:
for (int i = sizeof(uint32_t) - 1; i >= 0; --i)
*p++ = (unsigned char) ((number >> (i * 8)) & 0xFF);
It looks good otherwise.
Your code is reasonable (although I'd use uint8_t, since you are not using the bytes as “characters”, and Peter is of course right wrt the typo), and unlike the commonly found alternatives like
uint32_t number = 8;
uint8_t* p = (uint8_t *) &number;
or
union {
uint32_t number;
uint8_t bytes[4];
} val;
val.number = 8;
// access val.bytes[0] .. val.bytes[3]
is even guaranteed to work. The first alternative will probably work in a debug build, but more and more compilers might break it when optimizing, while the second one tends to work in practice just about everywhere, but is explicitly marked as a bad thing™ by the language standard.
I would drop the loop and use a "caller allocates" interface, like
int convert_32 (unsigned char *target, size_t size, uint32_t val)
{
if (size < 5) return -1;
target[0] = 7;
target[1] = (val >> 24) & 0xff;
target[2] = (val >> 16) & 0xff;
target[3] = (val >> 8) & 0xff;
target[4] = (val) & 0xff;
return 5;
}
This makes it easier for the caller to concatenate multiple fragments into one big binary packet and keep track of the used/needed buffer size.
Do you mean?
for (int i = sizeof(uint32_t) - 1; i >= 0; --i)
*p++ = (number >> (i * 8)) & 0xFF;
Another option to might be to do
// this would work on Big endian systems, e.g. sparc
struct unsignedMsg {
unsigned char type;
uint32_t value;
}
unsignedMsg msg;
msg.type = 7;
msg.value = number;
unsigned char *p = (unsigned char *) &msg;
or
unsigned char* p =
p[0] = 7;
*((uint32_t *) &(p[1])) = number;

how to make a bit-set/byte-array conversion in c

Given an array,
unsigned char q[32]="1100111...",
how can I generate a 4-bytes bit-set, unsigned char p[4], such that, the bit of this bit-set, equals to value inside the array, e.g., the first byte p[0]= "q[0] ... q[7]"; 2nd byte p[1]="q[8] ... q[15]", etc.
and also how to do it in opposite, i.e., given bit-set, generate the array?
my own trial out for the first part.
unsigned char p[4]={0};
for (int j=0; j<N; j++)
{
if (q[j] == '1')
{
p [j / 8] |= 1 << (7-(j % 8));
}
}
Is the above right? any conditions to check? Is there any better way?
EDIT - 1
I wonder if above is efficient way? As the array size could be upto 4096 or even more.
First, Use strtoul to get a 32-bit value. Then convert the byte order to big-endian with htonl. Finally, store the result in your array:
#include <arpa/inet.h>
#include <stdlib.h>
/* ... */
unsigned char q[32] = "1100111...";
unsigned char result[4] = {0};
*(unsigned long*)result = htonl(strtoul(q, NULL, 2));
There are other ways as well.
But I lack <arpa/inet.h>!
Then you need to know what byte order your platform is. If it's big endian, then htonl does nothing and can be omitted. If it's little-endian, then htonl is just:
unsigned long htonl(unsigned long x)
{
x = (x & 0xFF00FF00) >> 8) | (x & 0x00FF00FF) << 8);
x = (x & 0xFFFF0000) >> 16) | (x & 0x0000FFFF) << 16);
return x;
}
If you're lucky, your optimizer might see what you're doing and make it into efficient code. If not, well, at least it's all implementable in registers and O(log N).
If you don't know what byte order your platform is, then you need to detect it:
typedef union {
char c[sizeof(int) / sizeof(char)];
int i;
} OrderTest;
unsigned long htonl(unsigned long x)
{
OrderTest test;
test.i = 1;
if(!test.c[0])
return x;
x = (x & 0xFF00FF00) >> 8) | (x & 0x00FF00FF) << 8);
x = (x & 0xFFFF0000) >> 16) | (x & 0x0000FFFF) << 16);
return x;
}
Maybe long is 8 bytes!
Well, the OP implied 4-byte inputs with their array size, but 8-byte long is doable:
#define kCharsPerLong (sizeof(long) / sizeof(char))
unsigned char q[8 * kCharsPerLong] = "1100111...";
unsigned char result[kCharsPerLong] = {0};
*(unsigned long*)result = htonl(strtoul(q, NULL, 2));
unsigned long htonl(unsigned long x)
{
#if kCharsPerLong == 4
x = (x & 0xFF00FF00UL) >> 8) | (x & 0x00FF00FFUL) << 8);
x = (x & 0xFFFF0000UL) >> 16) | (x & 0x0000FFFFUL) << 16);
#elif kCharsPerLong == 8
x = (x & 0xFF00FF00FF00FF00UL) >> 8) | (x & 0x00FF00FF00FF00FFUL) << 8);
x = (x & 0xFFFF0000FFFF0000UL) >> 16) | (x & 0x0000FFFF0000FFFFUL) << 16);
x = (x & 0xFFFFFFFF00000000UL) >> 32) | (x & 0x00000000FFFFFFFFUL) << 32);
#else
#error Unsupported word size.
#endif
return x;
}
For char that isn't 8 bits (DSPs like to do this), you're on your own. (This is why it was a Big Deal when the SHARC series of DSPs had 8-bit bytes; it made it a LOT easier to port existing code because, face it, C does a horrible job of portability support.)
What about arbitrary length buffers? No funny pointer typecasts, please.
The main thing that can be improved with the OP's version is to rethink the loop's internals. Instead of thinking of the output bytes as a fixed data register, think of it as a shift register, where each successive bit is shifted into the right (LSB) end. This will save you from all those divisions and mods (which, hopefully, are optimized away to bit shifts).
For sanity, I'm ditching unsigned char for uint8_t.
#include <stdint.h>
unsigned StringToBits(const char* inChars, uint8_t* outBytes, size_t numBytes,
size_t* bytesRead)
/* Converts the string of '1' and '0' characters in `inChars` to a buffer of
* bytes in `outBytes`. `numBytes` is the number of available bytes in the
* `outBytes` buffer. On exit, if `bytesRead` is not NULL, the value it points
* to is set to the number of bytes read (rounding up to the nearest full
* byte). If a multiple of 8 bits is not read, the last byte written will be
* padded with 0 bits to reach a multiple of 8 bits. This function returns the
* number of padding bits that were added. For example, an input of 11 bits
* will result `bytesRead` being set to 2 and the function will return 5. This
* means that if a nonzero value is returned, then a partial byte was read,
* which may be an error.
*/
{ size_t bytes = 0;
unsigned bits = 0;
uint8_t x = 0;
while(bytes < numBytes)
{ /* Parse a character. */
switch(*inChars++)
{ '0': x <<= 1; ++bits; break;
'1': x = (x << 1) | 1; ++bits; break;
default: numBytes = 0;
}
/* See if we filled a byte. */
if(bits == 8)
{ outBytes[bytes++] = x;
x = 0;
bits = 0;
}
}
/* Padding, if needed. */
if(bits)
{ bits = 8 - bits;
outBytes[bytes++] = x << bits;
}
/* Finish up. */
if(bytesRead)
*bytesRead = bytes;
return bits;
}
It's your responsibility to make sure inChars is null-terminated. The function will return on the first non-'0' or '1' character it sees or if it runs out of output buffer. Some example usage:
unsigned char q[32] = "1100111...";
uint8_t buf[4];
size_t bytesRead = 5;
if(StringToBits(q, buf, 4, &bytesRead) || bytesRead != 4)
{
/* Partial read; handle error here. */
}
This just reads 4 bytes, and traps the error if it can't.
unsigned char q[4096] = "1100111...";
uint8_t buf[512];
StringToBits(q, buf, 512, NULL);
This just converts what it can and sets the rest to 0 bits.
This function could be done better if C had the ability to break out of more than one level of loop or switch; as it stands, I'd have to add a flag value to get the same effect, which is clutter, or I'd have to add a goto, which I simply refuse.
I don't think that will quite work. You are comparing each "bit" to 1 when it should really be '1'. You can also make it a bit more efficient by getting rid of the if:
unsigned char p[4]={0};
for (int j=0; j<32; j++)
{
p [j / 8] |= (q[j] == `1`) << (7-(j % 8));
}
Going in reverse is pretty simple too. Just mask for each "bit" that you set earlier.
unsigned char q[32]={0};
for (int j=0; j<32; j++) {
q[j] = p[j / 8] & ( 1 << (7-(j % 8)) ) + '0';
}
You'll notice the creative use of (boolean) + '0' to convert between 1/0 and '1'/'0'.
According to your example it does not look like you are going for readability, and after a (late) refresh my solution looks very similar to Chriszuma except for the lack of parenthesis due to order of operations and the addition of the !! to enforce a 0 or 1.
const size_t N = 32; //N must be a multiple of 8
unsigned char q[N+1] = "11011101001001101001111110000111";
unsigned char p[N/8] = {0};
unsigned char r[N+1] = {0}; //reversed
for(size_t i = 0; i < N; ++i)
p[i / 8] |= (q[i] == '1') << 7 - i % 8;
for(size_t i = 0; i < N; ++i)
r[i] = '0' + !!(p[i / 8] & 1 << 7 - i % 8);
printf("%x %x %x %x\n", p[0], p[1], p[2], p[3]);
printf("%s\n%s\n", q,r);
If you are looking for extreme efficiency, try to use the following techniques:
Replace if by subtraction of '0' (seems like you can assume your input symbols can be only 0 or 1).
Also process the input from lower indices to higher ones.
for (int c = 0; c < N; c += 8)
{
int y = 0;
for (int b = 0; b < 8; ++b)
y = y * 2 + q[c + b] - '0';
p[c / 8] = y;
}
Replace array indices by auto-incrementing pointers:
const char* qptr = q;
unsigned char* pptr = p;
for (int c = 0; c < N; c += 8)
{
int y = 0;
for (int b = 0; b < 8; ++b)
y = y * 2 + *qptr++ - '0';
*pptr++ = y;
}
Unroll the inner loop:
const char* qptr = q;
unsigned char* pptr = p;
for (int c = 0; c < N; c += 8)
{
*pptr++ =
qptr[0] - '0' << 7 |
qptr[1] - '0' << 6 |
qptr[2] - '0' << 5 |
qptr[3] - '0' << 4 |
qptr[4] - '0' << 3 |
qptr[5] - '0' << 2 |
qptr[6] - '0' << 1 |
qptr[7] - '0' << 0;
qptr += 8;
}
Process several input characters simultaneously (using bit twiddling hacks or MMX instructions) - this has great speedup potential!

Converting Char array to Long in C

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.
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.
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.
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.
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 */
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;
}
This is dirty but it works:
unsigned char myCharArray[8];
// Put some data in myCharArray here...
long long integer = *((long long*) myCharArray);
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.
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

Resources