I personally use a function show_bytes as follows:
#include<stdio.h>
typedef char *byte_pointer;
void show_bytes (byte_pointer x)
{
int length = sizeof(float);
int i;
for(i = 0;i <length;i++)
{
printf("%2x",*(x+i));
printf("\n");
}
}
int main()
{
float obj;
printf("please input the value of obj:");
scanf("%f",&obj);
show_bytes((byte_pointer) &obj);
}
when i input 120.45,which should be 0x42f0e666
please input the value of obj:120.45
66
ffffffe6
fffffff0
42
why so many 'f' before the e6 and f0 while i use %.2x.
Your function should be:
void show_bytes (byte_pointer x)
{
int i;
for(i = 0; i <sizeof(float); i++)
{
printf("0x%2X\n", (unsigned int)(*(x++) & 0xFF));
}
}
or
typedef uint8_t *byte_pointer;
void show_bytes (byte_pointer x)
{
int i;
for(i = 0; i <sizeof(float); i++)
{
printf("0x%2X\n", *(x++));
}
}
In your code the problem is that the pointer type is signed an is promoted to signed int by printf.
%2X format does not limit the output digit, tells only to printf that the result string must be at least 2 characters long.
First solution: the value is promoted to signed int but the passed
value is truncated to the LSB.
Second example: value is truncated by the type of pointer, that
is unsigned char.
The rule is: to raw access memory, always use unsigned types.
Related
I want to write a program with following signature where the function will be applied to all the elements of the array in c.
void map(unsigned(*function_name)(unsigned),
size_t funct_length,
arr_name[funct_length]);
Everything is unsigned.
There are a few blanks on your question, but the following code provides you with a starting point. Some issues:
(*function_name)(unsigned) is a pointer function, the other parameters are the array size and a pointer to the array, I produced two invented functions, map_add_point and map_remove_point, so each function will be applied to all the elements of the array.
void map(unsigned (*function_name)(unsigned), size_t funct_length, unsigned arr_name[]);
unsigned map_add_point(unsigned);
unsigned map_remove_point(unsigned);
int main()
{
unsigned points_a[] = {1,2,3};
unsigned points_b[] = {1,2};
map(map_add_point, sizeof(points_a)/sizeof(unsigned), points_a);
map(map_remove_point, sizeof(points_a)/sizeof(unsigned), points_b);
return 0;
}
void map(unsigned (*funct_length)(unsigned), size_t length, unsigned arr_name[])
{
size_t n;
for (n = 0; n < length; n++)
{
(*funct_length) (arr_name[n]);
}
}
unsigned map_add_point(unsigned point)
{
printf("\nPoint to add: %d", point);
return 0;
}
unsigned map_remove_point(unsigned point)
{
printf("\nPoint to remove: %d", point);
return 0;
}
Minimalistic:
void map(unsigned(*function_name)(unsigned), size_t funct_length, unsigned arr_name[funct_length])
{
while(funct_length--)
{
*arr_name = function_name(*arr_name);
arr_name++;
}
}
I am trying to print out IEEE754 after taking integer type but it does not show the proper answer for me.
I want to pass the integer to the function "void ieee(int x)" in the main method, then it will print out the IEEE754 format.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int binary(int n, int i)
{
int k;
for (i--; i >= 0; i--)
{
k = n >> i;
if (k & 1)
printf("1");
else
printf("0");
}
}
typedef union
{
int f;
struct
{
unsigned int mantissa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} field;
} myfloat;
void ieee(int x)
{
int i;
myfloat var = (myfloat)x;
printf("%d ",var.field.sign);
binary(var.field.exponent, 8);
printf(" ");
binary(var.field.mantissa, 23);
printf("\n");
}
int main()
{
int x = 3;
ieee(x);
return 0;
}
You are doing a type punning between an int and a struct type holding the internal representation of a float.
This will give you wrong answers.
If you want to know the floating-point representation of an integer number, the correct result can be obtained by doing a previous cast to float.
int x = 3;
myfloat var;
var.f = (float)x;
binary(var.field.exponent, 8);
binary(var.field.mantissa, 23);
Besides, take in account that one cannot assume that IEEE floating-point representation is being used for float.
For example, see this link:
Macro __STDC_IEC_559__
On the other hand, bit-fields are not necessarily contiguous in all implementations.
See Bitfield disadvantages.
The following uses a union to reinterpret the representation of a float as a 32-bit unsigned integer. This is valid in C. In C++, a union cannot be used for this, and it is necessary to copy the bytes from a float into an integer, as with memcpy.
#include <limits.h> // For CHAR_BIT (overkill but demonstrates some portability).
#include <stdint.h>
#include <stdio.h>
static void DisplayFloat(float x)
{
// Use a union to reinterpret a float as a 32-bit unsigned integer.
union { float f; uint32_t u; } t = { x };
// Ensure float and uint32_t are the same width.
_Static_assert(sizeof t.f == sizeof t.u,
"float and uint32_t must be same width.");
// Display the bits of the unsigned integer.
for (int i = sizeof t.u * CHAR_BIT - 1; 0 <= i; --i)
putchar('0' + (t.u >> i & 1));
putchar('\n');
}
int main(void)
{
DisplayFloat(3);
}
I have a unsigned char array containing the following value : "\x00\x91\x12\x34\x56\x78\x90";
That is number being sent in Hexadecimal format.
Additionally, it is in BCD format : 00 in byte, 91 in another byte (8 bits)
On the other side I require to decode this value as 0091234567890.
I'm using the following code:
unsigned int conver_bcd(char *p,size_t length)
{
unsigned int convert =0;
while (length--)
{
convert = convert * 100 + (*p >> 4) * 10 + (*p & 15);
++p
}
return convert;
}
However, the result which I get is 1430637214.
What I understood was that I'm sending hexadecimal values (\x00\x91\x12\x34\x56\x78\x90) and my bcd conversion is acting upon the decimal values.
Can you please help me so that I can receive the output as 00911234567890 in Char
Regards
Karan
It looks like you are simply overflowing your unsigned int, which is presumably 32 bits on your system. Change:
unsigned int convert =0;
to:
uint64_t convert = 0;
in order to guarantee a 64 bit quantity for convert.
Make sure you add:
#include <stdint.h>
Cast char to unsigned char, then print it with %02x.
#include <stdio.h>
int main(void)
{
char array[] = "\x00\x91\x12\x34\x56\x78\x90";
int size = sizeof(array) - 1;
int i;
for(i = 0; i < size; i++){
printf("%02x", (unsigned char )array[i]);
}
return 0;
}
Change return type to unsigned long long to insure you have a large enough integer.
Change p type to an unsigned type.
Print value with leading zeros.
unsigned long long conver_bcd(const char *p, size_t length) {
const unsigned char *up = (const unsigned char*) p;
unsigned long long convert =0;
while (length--) {
convert = convert * 100 + (*up >> 4) * 10 + (*up & 15);
++up;
}
return convert;
}
const char *p = "\x00\x91\x12\x34\x56\x78\x90";
size_t length = 7;
printf( "%0*llu\n", (int) (length*2), conver_bcd(p, length));
// 00911234567890
I am trying to understand number representation in C.
I am working on a code segment which looks like the one below.
#include <stdio.h>
#include <string.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, int len)
{
int i;
for (i = 0; i < len; i++)
printf(" %.2x", start[i]);
printf("\n");
}
void show_int(int x) {
show_bytes((byte_pointer) &x, sizeof(int));
}
void show_unsigned(short x) {
show_bytes((byte_pointer) &x, sizeof(unsigned));
}
int main(int argc,char*argv[])
{
int length=0;
unsigned g=(unsigned)length;// i aslo tried with unsigned g=0 and the bytes are the same
show_unsigned(g);
show_int(length);
printf("%d",g);//this prints 0
return 0;
}
Here, show_unsigned() and show_int() prints the byte representations of the variables specified as arguments.For int length the byte representation is all zeroes as expected, but for unsigned g, the byte representation is 00 00 04 08.But when I print g with a %d, I get 0(so i suppose the numeric value is interpreted as 0 )
Please could somebody explain how this is happening.
In:
void show_unsigned(short x) {
show_bytes((byte_pointer) &x, sizeof(unsigned));
}
You declared the argument short x which is smaller than int x so you ignored some of the 00 and your print function is displaying adjacent garbage.
You're reading sizeof(unsigned) bytes in a short. short isn't guaranteed to be the same size as unsigned, hence, when reading the bytes next to your short, garbage data is read.
To fix this, either pass your argument as an unsigned, or when using sizeof, use sizeof(short).
what you are doing doesn't make any sense, particularly with the type conversions that you have occurring. Someone else already pointed out my point about the conversion to short
Rather than writing an absurd number of functions try doing this
void show_bytes( void *start, unsigned int len ) {
unsigned char* ptr = (unsigned char *) start;
unsigned int i = 0;
for ( i = 0; i < len; ++i, ++ptr ) {
printf( " %.2x", ptr[0] );
}
}
Instead of calling as you had been just call it like:
show_bytes( (void *)&x, sizeof(x));
And if thats too much typing make a macro out of that. now it works for any type you come up with.
Briefly: Question is related to bitwise operations on hex - language C ; O.S: linux
I would simply like to do some bitwise operations on a "long" hex string.
I tried the following:
First try:
I cannot use the following because of overflow:
long t1 = 0xabefffcccaadddddffff;
and t2 = 0xdeeefffffccccaaadacd;
Second try: Does not work because abcdef are interpreted as string instead of hex
char* t1 = "abefffcccaadddddffff";
char* t2 = "deeefffffccccaaadacd";
int len = strlen(t1);
for (int i = 0; i < len; i++ )
{
char exor = *(t1 + i) ^ *(t2 + i);
printf("%x", exor);
}
Could someone please let me know how to do this? thx
Bitwise operations are usually very easily extended to larger numbers.
The best way to do this is to split them up into 4 or 8 byte sequences, and store them as an array of uints. In this case you need at least 80 bits for those particular strings.
For AND it is pretty simple, something like:
unsigned int A[3] = { 0xabef, 0xffcccaad, 0xddddffff };
unsigned int B[3] = { 0xdeee, 0xfffffccc, 0xcaaadacd };
unsigned int R[3] = { 0 };
for (int b = 0; b < 3; b++) {
R[b] = A[b] & B[b];
}
A more full example including scanning hex strings and printing them:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef unsigned int uint;
void long_Print(int size, const uint a[]) {
printf("0x");
for (int i = 0; i < size; i++) {
printf("%x", a[i]);
}
}
void long_AND(int size, const uint a[], const uint b[], uint r[]) {
for (int i = 0; i < size; i++) {
r[i] = a[i] & b[i];
}
}
// Reads a long hex string and fills an array. Returns the number of elements filled.
int long_Scan(int size, const char* str, uint r[]) {
int len = strlen(str);
int ri = size;
for (const char* here = &str[len]; here != str; here -= 8) {
if (here < str) {
char* tmp = (char*)malloc(4);
tmp[0] = '%';
tmp[1] = (char)(str - here + '0');
tmp[2] = 'x';
tmp[3] = '\0';
sscanf(str, tmp, &r[ri--]);
free(tmp);
break;
}
else {
sscanf(here, "%8x", &r[ri--]);
}
}
for (; ri >= 0; ri--) {
r[ri] == 0;
}
return size - ri;
}
int main(int argc, char* argv[])
{
uint A[3] = { 0 };
uint B[3] = { 0 };
uint R[3] = { 0 };
long_Scan(3, "abefffcccaadddddffff", A);
long_Scan(3, "deeefffffccccaaadacd", B);
long_Print(3, A);
puts("\nAND");
long_Print(3, B);
puts("\n=");
long_AND(3, A, B, R);
long_Print(3, R);
getchar();
return 0;
}
You'll certainly need to use a library that can handle arbitrarily long integers. Consider using libgmp: http://gmplib.org/
Before you can do any sort of bitwise operations, you need to be working with integers. "abeffccc" is not an integer. It is a string. You need to use something like strtol
to first convert the string to an integer.
If your values are too big to fit into a 64-bit long long int (0xFFFFFFFF,FFFFFFFF) then you'll need to use a Big Integer library, or something similar, to support arbitrarily large values. As H2CO3 mentioned, libgmp is an excellent choice for large numbers in C.
Instead of using unsigned long directly, you could try using an array of unsigned int. Each unsigned int holds 32 bits, or 8 hex digits. You would therefore have to chop-up your constant into chunks of 8 hex digits each:
unsigned int t1[3] = { 0xabef , 0xffcccaad , 0xddddffff };
Note that for sanity, you should store them in reverse order so that the first entry of t1 contains the lowest-order bits.