Print bits from argv - c

I'm sure the answer is simple but I can't get my head around so I hope you can help me :)
I'm trying to print the bits of a unsigned char, here with the value 2, the issue is that I get a wrong answer when casting from argv[1][0] and the good one when sending directly the number 2.
void print_bits(unsigned char octet)
{
int i;
unsigned char b;
i = 8;
while (i--)
{
b = (octet >> i & 1) + '0';
write(1, &b, 1);
}
}
int main(int argc, char **argv)
{
print_bits((unsigned char)argv[1][0]);
write(1, "\n", 1);
print_bits(2);
write(1, "\n", 1);
return (0);
}
gives me :
00110010
00000010
I notice when debugging that, if I print the "octet" variable at the start of print_bits, I get the ASCII value of 2 when casting from argv and the value "\002" when directly inputting the value 2.
It feels like a casting issue ?
Thank you!

char are just integers, when you input '2' from argv, it reads the character '2' (which is equal to 50 in ASCII). In your second case, you input the int 2, hence the two different outputs. Your function is correct and so is the output.

Related

XOR two hexadecimal strings(unmasking) in C

I wanted to unmask a hex string using the following algorithm in C
j = i MOD 4 transformed-octet-i = original-octet-i XOR masking-key-octet-j
#include<stdlib.h>
#include<string.h>
int main()
{
char masked[]="951bfdcdc113ebca921fe9dc";
char masking_key[]="e17e8eb9";
char *unmasked;
int length=strlen(masked);
unmasked=malloc(sizeof(char)*(length+1));
int i=0;
for(i=0;i<length;i++)
{
unmasked[i]=masked[i]^masking_key[i%4];
}
printf("%s\n",unmasked);
return 0;
}
The output I am getting is \UT instead of 74657374206d657373616765. It would be really helpful if someone could help me fix the error here.
You need to convert from string format to raw integers before doing the XOR, then convert back before printing it as a string. Otherwise you'll XOR the symbol values, not the raw values.
You can convert the whole string in one go with strtol(data, 0, 16). But one of the common details that makes programmers different from the code monkeys is the ability to code trivial string-integer conversions without the help of library functions. So here is a a simplified code doing just that - be aware of the complete lack of error handling, as this is just quick & dirty code:
#include <stdio.h>
#include <stdlib.h>
char hexlify (char nibble)
{
return "0123456789abcdef"[nibble];
}
char unhexlify (char ch)
{
if(ch>='0' && ch<='9')
return ch - '0';
if(ch>='a' && ch<='f')
return ch - 'a' + 0xA;
return 0;
}
int main (void)
{
char masked[]="951bfdcdc113ebca921fe9dc";
char masking_key[]="e17e8eb9";
char *unmasked;
size_t length = sizeof masked - 1;
unmasked = malloc(length + 1);
for(size_t i=0;i<length;i++)
{
char op1 = unhexlify(masked[i]);
char op2 = unhexlify(masking_key[i%4]);
unmasked[i]= hexlify(op1 ^ op2);
}
unmasked[length]='\0';
printf("%s\n",unmasked);
free(unmasked);
return 0;
}
Output:
74651cb3206d0ab4736108a2
What you're doing here is not xoring the hexadecimal bytes, but xoring the characters representing them.
While the ideal process would be (0x95 ^ 0xe1) + (0xbf ^ 7e) + ..., what you're doing is xoring the ascii values of each character, meaning ('9' ^ 'b') + ('5' ^ '1') + ....
What you need to do is first transform the hexadecimal string to the bytes themselves (bytes.fromhex("951bfdcdc113ebca921fe9dc") in python), and only then XOR them. The way I would do that is with sscanf("%2x", ...).
For example:
#include <stdio.h>
int main()
{
unsigned char a = 0;
scanf("%2hhx", &a);
}

integers in char array

I want know how integers are treated in char arrays. For example when we use scanf() & printf() functions for single characters we use "%c", for string values "%s", etc. I used "%s" for printing the char array with integers. But it prints some junk characters as the output.
While working with integer variables directly, it's simple as:
int i = 7;
printf("%d", i);
and while working with an array of characters, you could create helper functions that will do the conversion between char* <-> int so that you end up with more portable solution:
int toInt(unsigned char* p) {
return *(p + 0) << 24 | *(p + 1) << 16 | *(p + 2) << 8 | *(p + 3);
}
...
unsigned char arr[4] = {0,0,0,4};
int i = toInt(&arr[0]);
printf("%d", i);
should print 4
Alternatively you might use simple cast:
unsigned char arr[4] = {0,0,0,4};
int* i = &arr[0];
printf("%d", *i);
but that solution will be depend on endianness. On ideone.com it prints 67108864.
If you know the length of each phone number will be the same, you could pad out the front of the number with zeros. e.g. to pad each number out to 10 digits, putting 0's in front when necessary:
int d = 123456789;
printf("%d\n", d); // prints 123456789
printf("%010d\n", d); // prints 0123456789
d = 12345678;
printf("%010d\n", d); // prints 0012345678 :-(
It's hard to guess more about the requirements without seeing the code. There's lots of examples of formatting with printf, eg: http://www.codingunit.com/printf-format-specifiers-format-conversions-and-formatted-output

char* decimal to hexadecimal in little-endian

I have an issue where I am inputting an decimal argument to my code:
./a.out 650
and would like to simply convert the decimal value into hex and output it in a little-endian format:
0A28
My current solution has been to convert the char* to decimal using atoi (we can assume the input is decimal, no worry about error cases).
I have read that I could create an int* and cast it to the char*, something like this:
char* bar = argv[1];
int* foo = (char*)&bar;
and that iterating through it would produce the solution I needed, but I do not quite understand how that would work.
Like this:
#include <stdio.h>
#include <stdlib.h>
unsigned long int n = strtoul(argv[1], NULL, 0);
unsigned char const * p = (unsigned char const *)&n;
for (size_t i = 0; i != sizeof n; ++i)
printf("%02X", p[i]);
To print the reverse endianness, use sizeof n - i - 1 in place of i.
This should take the program's first parameter and print it out as a big endian hexadecimal number and little endian hexadecimal.
int main(int argc, char *argv[]) {
if (argc != 2) return -1;
char *endptr;
unsigned long d = strtoul(argv[1], &endptr, 10);
if (*endptr) {
printf("Not a decimal number '%s'\n", argv[1]);
return 1;
}
printf("%lX\n", d); // normal
do {
printf("%02hhX", (unsigned char) d); // little endian first
d >>= 8;
} while (d);
printf("\n");
return 0;
}

How to convert a string to binary?

I'm working on a C project and I have some instructions of type:
add $1 $2 $3
So I'm reading the line as a string, parsing through it and have a corresponding integer for add, say - 2. Could anyone please tell me how I could convert this to binary in order to write it to a file?
The registers are 5 bits and the operation is 6 bits. The total will be 32 (the last 10 bits are unused).
So the registers are stored in say op[] = "2", char r1[] = "1", char r2[] = "2" etc (note that register number can be as high as 31). Could anyone give me an example for a function that would convert this to binary in the format 000010 00001 00010 00011 0000000000
The easiest way will be using a bit field:
struct code {
unsigned opcode : 6;
unisgned operand1 : 5;
unisgned operand2 : 5;
unisgned operand2 : 5;
} test_code;
Now you can simply assign to the different members:
test_code.opcode = 0x02;
test_code.operator1 = 0x01;
test_code.operator2 = 0x02;
test_code.operator3 = 0x03;
atoi(op) will give you 2, so you can just string it together
As far as putting it into that structure you want, just create a structure that has bitfields in it and place it in a union with a 32 bit unsigned integer, and you can take the value directly.
Quick pseudo code
const char* int32_to_bin(int32_t value) {
int pos = 0;
char output[33];
while(value > 0) {
if (value & 1) output[pos++] = '1';
else output[pos++] = '0';
value >>= 1;
}
output[pos] = 0;
return output;
}
What you're asking is a C question but you tag as objective-c so I'll cover both.
C:
These variables such as op[].. are really defined as like char op[..] (not sure if your length), which are C strings of course.
So the operation is 6 bit and each register is 5 bits, that's 15 + 6 = 21 bit word. I'll assume the top 11 bits are zeroes.
What you need are 4 more variables that are integers:
int opint; int r0int; int r1int; int r2int;
You want the integer value of those strings to go in to those integers. You can use atoi() to achieve this, such as opint = atoi(op);
Now that you've got your integers derived from strings, you need to create the 32 bit word. The easiest way to do this is to first create one integer that holds those bits in the right place. You can do it (assuming 32 bit integers) like this:
int word = 0;
word |= ((opint & 0x3f) << (21 - 6))) |
(r0int & 0x1f) << (21 - 11)) |
(r1int & 0x1f) << (21 - 16))
(r2int & 0x1f));
Where the << is shifting in to place. After this, you should have the word integer properly formed. Next, just turn it in to a binary representation (if that's even necessary? Not sure on your application)
Objective-C
The only difference is that I assume those strings start as NSString *op; etc. In this case, get the integers by opint = [op intValue];, then form the word as I describe.
This code will convert a string to binary
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* stringToBinary(char* s) ;
void binchar(char output[], char character);
void itoa(int value, char* str, int base);
int main(int argc, char const *argv[])
{
printf("%s\n", stringToBinary("asdf") );
}
char* stringToBinary(char* s) {
if(s == NULL) return 0; /* no input string */
size_t len = strlen(s);
char *binary = malloc(len*8 + 1); // each char is one byte (8 bits) and + 1 at the end for null terminator
int i =0;
char output[9];
for(i=0; i< len; i++){
binchar(output, s[i]);
strcat(binary,output);
}
return binary;
}
void binchar(char output[], char character)
{
//char output[9];
itoa(character, output, 2);
}
// since GCC is not fully supporting itoa function here is its implementaion
// itoa implementation is copied from here http://www.strudel.org.uk/itoa/
void itoa(int value, char* str, int base) {
static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz";
char* wstr=str;
int sign;
// Validate base
if (base<2 || base>35){ *wstr='\0'; return; }
// Take care of sign
if ((sign=value) < 0) value = -value;
// Conversion. Number is reversed.
do *wstr++ = num[value%base]; while(value/=base);
if(sign<0) *wstr++='-';
*wstr='\0';
// Reverse string
void strreverse(char* begin, char* end);
strreverse(str,wstr-1);
}
void strreverse(char* begin, char* end) {
char aux;
while(end>begin)
aux=*end, *end--=*begin, *begin++=aux;
}

Problems writing the memset function

I am writing the memset function and my code is below, I am having a problem
void* memsetFun(void* pointer, int c, int size) {
if ( pointer != NULL && size > 0 ) {
unsigned char* pChar = pointer;
int i = 0;
for ( i = 0; i < size; ++i) {
unsigned char temp = (unsigned char) c;
*pChar++ = temp; // or pChar[i] = temp (they both don't work)
}
}
return pointer;
}
I also tried pChar[i] = the value we want and still not working. It gives me some trash numbers that do not make any sense.
And I am calling it:
memsetFun(address, num, size);
printf("value at %p is %d\n", address, *((int*) address));
Where I call the address (I just input the address)
For example, if you to print the chars ( c ) it prints like a weird char that looks like ( for the value 4 )
0 0
0 4
Your code looks fine to me and several people here have commented that it works on their system.
So the obvious thing to do is to debug it - that's a skill that will come in handy quite a bit in future :-) You should learn it now.
What does the following code output when you run it?
void* memsetFun(void* pointer, int c, int size) {
printf("A %x %d %d\n", pointer, c, size);
if ( pointer != NULL && size > 0 ) {
printf("B\n");
unsigned char* pChar = pointer;
int i = 0;
for ( i = 0; i < size; ++i) {
printf("C %d (%d)", i, *pChar);
unsigned char temp = (unsigned char) c;
*pChar++ = temp; // or pChar[i] = temp (they both don't work)
printf(" -> (%d)", i, *(pChar-1));
}
}
printf("D\n");
return pointer;
}
From the output, it should be clear what paths the code is taking and what your parameters are (which will greatly assist the debugging process).
Update:
If you're filling your memory block with anything other than zeros and using this:
printf("value at %p is %d\n", address, *((int*) address));
to print it out, you will get strange results.
You're basically asking for a number of those bytes to be interpreted as an integer. So, for example, if you filled it with 0x02 bytes and you have a 4-byte integer type, you will get the integer 0x02020202 (33686018), not 0x02 as you may expect. If you want to see what the first character value is, use:
printf("value at %p is %d\n", address, *((char*) address));
And based on your latest question update:
For example, if you to print the chars ( c ) it prints like a weird char that looks like ( for the value 4 )
0 0
0 4
If that's a single character and you're printing it as a character, there's probably nothing wrong at all. Many output streams will give you that for a control character (CTRL-D in this case, ASCII code 4). If you instead filled it with ASCII code 0x30 (48), you would see the character '0' or ASCII 0x41 (65) would give you 'A'.
As pointed out already, your function works as it should. Here is a complete example:
#include <assert.h>
#include <string.h>
void* memsetFun(void* pointer, int c, int size) {
if ( pointer != NULL && size > 0 ) {
unsigned char* pChar = pointer;
int i = 0;
for ( i = 0; i < size; ++i) {
unsigned char temp = (unsigned char) c;
*pChar++ = temp; // or pChar[i] = temp (they both don't work)
}
}
return pointer;
}
int main() {
// Your memset
char a[10];
memsetFun(a, 'A', sizeof(a));
// Uses system memset for verification
char b[10];
memset(b, 'A', sizeof(b));
assert(sizeof(a) == sizeof(b));
assert(memcmp(a, b, sizeof(b)) == 0);
return 0;
}
return p; prevents this from compiling: p is not defined.
A minor efficiency issue—in practice it would have little effect, since any good compiler would rearrange it, but coding perfectionists wouldn't allow it to remain—the assignment to temp is inside the loop, but it is the same assignment every time. That is, the assignment to temp can be moved before the loop.
You return p, which isn't defined/doesn't point to anything in particular. Maybe you meant pointer?
The code is logically correct. With the p => pointer change it works correctly.
Clarify how exactly it is "not working". Perhaps you are not understanding what it is supposed to do?
You are probably getting trash numbers because you are casting from an int (4 bytes) to an unsigned char (1 byte), so if c > 255 or < 0 you won't be memsetting the values you are expecting to be.
I ran a test if your program setting the memory of an int vector of 5 elements setting with the value 0x01.
The problem here is that you are iterating in a vector of int for example (which is 4 bytes) but iterating over it using char pointer arithmetic (1 byte). If you want to memset 0x01 for example you will write this number per value in the vector: 00000001000000010000000100000001
which gives me the same value using the original memset.
Your function, as is, works for me.
I suppose you're calling it wrong. I call it like this
char a[100];
memsetFun(a, 0, sizeof a);
int b[100];
memsetFun(b, 0, sizeof b);
How are you calling your memsetFun()?
Edit
With
int b[100];
memsetFun(b, 9, sizeof b);
as an int is made up of 4 bytes (on my system) each value will be set to 0x09090909 or 151587081.
That is exactly what it's supposed to do. Your function is working perfectly fine. The value "0x4" is not the ASCII character '4'.

Resources