[SOLVED] The best way to perform bitwise operation on hexadecimal value ?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
The best way to perform bitwise operation on hexadecimal value ?
Hi
The problem is :i have a hex value just like bellow:
unsigned char * temp = "\x4b001cdb3349"
ok now i want to set specific bit of this string (change that bit to 1) in C.
I know many ways are exist to do that but maybe the way i choose has unnecessary overhead.
I can read the first byte (4b) convert to decimal value and do OR with the value that its bits is set to 1 (this could be a one solution).
That's not a hex value, it's a string. Are you trying to set a bit in the string, or are you trying to read two characters in the string as a single hex byte, set a bit in that, and then convert back to a pair of characters and insert it back into the string?
For example, take the string "4a"
If you interpret the characters in this string as two hex values, you get the decimal number 74, and the binary number 01001010. If you want to set the fifth bit, you would get 01011010, or decimal number 90, or hex number 5a. Then you could convert this back to the string "5a".
On the other hand, if you set the fifth bit in your string, you get a very different answer. The ASCII characters "4a" are the hex numbers 34 and 61 respectively (52 and 97 in decimal). This converts to the binary numbers 00110100 and 01100001. If you set the fifth bit here, you get 00110100 and 01110001, 34 and 71 in hex, 52 and 113 in decimal, which maps back to the ASCII characters "4q".
Last edited by suicidaleggroll; 05-15-2014 at 02:31 PM.
Okay, with a little finagling you should be able to sccanf() that string-value using an appropriate format-string to get your binary number. (A longint, looks like.) Then, you can perform the bitwise operations against that.
First, convert the value and store it in a longint variable. Trap any exceptions that occur, and deal with them appropriately.) Then, mash the bits.
You need to be more specific about the problem you have. Provide working code and then we will see. To change one bit of a certain variable you can use a mask and the | (logical or) operator. This is the usual way to do it, but your code doesn't make sense.
Code:
bash-4.2$ cat str.c
#include <stdio.h>
int main (void)
{
unsigned char * temp = "\x4b001cdb3349";
printf ("%s\n", temp);
return 0;
}
bash-4.2$ compile str.c
str.c: In function 'main':
str.c:5:26: warning: hex escape sequence out of range [enabled by default]
unsigned char * temp = "\x4b001cdb3349";
^
str.c:5:26: warning: pointer targets in initialization differ in signedness [-Wpointer-sign]
bash-4.2$ ./str
I
If you had an actual string, you would have to convert it using scanf() or atoi().
And it works.
Actually i am working on IP packet header.
I need to set a specific bit inside IP packet header in kernel using netfilter loadable kernel module.
I have access to IP header and i want to set some bits to 1 in the header.
For example i want to read specific byte from IP option field and set some bits to 1.
I have tested it by copying IP header to an unsigned char * variable and perform bitwise operation on it and it worked.
but now i want to perform the operation on ip packet header directly.
This code set the first bit of Twentieth-first byte to 1 in temp variable but i want to perform this operation on same byte of the IP header directly.
any suggestion would be greatly appreciated.
Okay, so maybe I'm not understanding the problem in its entirety (I don't do well w/o pix :-P). Though if you want to set the 21st byte in the IP header to 1 (ie 0000 0001), then you should be able to do it with something like this (untested, but should work):
I'm assuming "ip_header" is local, and not a ptr...if it's a ptr just remove the ampersand.
No need to copy it into a temp variable, just set it directly in the ip_header.
Maybe I'm misunderstanding something about what you're trying to do (probably the case, lol).
EDIT:
Note that you should use "uint8_t" instead of "char" for stuff like this, as uint8_t is guaranteed to be 8 bits, char is not (ie. unicode). Makes the code a bit more portable. Also note that (especially with IP stuff) that this may not be endian safe.
Dear Syndacate
thanks to answer, it is not completely same but ur solution is work for me.
I want the to set a specific bit of specific byte for example "first bit of 21st byte".
i problem solved.
Lets i illustrate what i want to do.
For example, this is the ip header : "00 4c .... 0a 04 00 00"
Lets assume the last fourth bytes are 21st to 24st bytes of ip header.
Then i want to set second bit of 22st byte to 1.
I would replace insertByte with just 1<<N, where N is the bit you want to set minus 1
eg:
*(temp+22) = *(temp+22) | (1<<1);
Or if you must use hex, just use hex, I don't understand why you're futzing around with a char * and that weird "\x" notation. I'm pretty sure that's not even a valid escape sequence...
Lets i fixed the errors;
1 - i don't need to allocate any memory to temp variable and at the end of program kfree(insertByte)
or
2 - just kfree temp and insertByte
Would it not be better to use a standard header with the defines available there?
On my Debian system that would appear to be /usr/include/netinet/ip.h. That header seems to define the available fields and flags and would make the purpose of your code much clearer.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.