Convert float 32 bit big endian to little endian - c

My data is a 2d 32 bit 2-D pointer image which is in big endian and I wish to convert in to little endian. Please check the following code:
float** ReverseFloat( const float **inFloat )
{
float **retVal;
char *floatToConvert = ( char* ) && inFloat;
char *returnFloat = ( char* ) && retVal;
// swap the bytes into a temporary buffer
returnFloat[0] = floatToConvert[3];
returnFloat[1] = floatToConvert[2];
returnFloat[2] = floatToConvert[1];
returnFloat[3] = floatToConvert[0];
return retVal;
}
Hi. As per all of your advice, I tried the following code but it gives all zero values:
float **swapend( float **in ,float **out , int h, int v)
{
char *floatToConvert = ( char* ) & in;
char *returnFloat = ( char *) & out;
for (int m=0; m<h; m++)
for (int k=0; k<v; k++)
{
for (int i=0; i<sizeof(float); i++)
returnFloat[sizeof(float)-1-i] = floatToConvert[i];
}
return out;
}
Thank you.

This won't work reliably. You create a local variable retVal and at the end, you return it. The value of this variable will eventually be random after the function ends.
I think this approach would be better since the compiler will do most of the necessary copying:
float be2le( char * floatToConvert ) {
float buffer;
char * returnFloat = (char *) &buffer;
...swap...
return buffer;
}

&& is the logical and operator (it may also carry a pointer like semantic as a gnu extension, but this is non portable), while & is the "address of” operator. You don't need to use pointers of pointers either:
float ReverseFloat(float inFloat ){
float retVal;
char *floatToConvert = ( char* ) &inFloat;
char *returnFloat = ( char* ) &retVal;
// swap the bytes into a temporary buffer
returnFloat[0] = floatToConvert[3];
returnFloat[1] = floatToConvert[2];
returnFloat[2] = floatToConvert[1];
returnFloat[3] = floatToConvert[0];
return retVal;
}
Note that this function works both ways: it let you convert from one endianness to the other.
Following your update: if you wish to convert several values contained in an array, just apply this function on each of them sequentially:
void ReverseFloatArray(unsigned int count, float *in, float *out){
unsigned int i;
for (i = 0; i < count; i++)
out[i] = ReverseFloat(in[i]);
}

Related

How to alter pointer value within a function in C

I was wondering if you could help me overcome a hurdle I've run into with my C syntax. I have written the function:
binary_and_trim(char *password, unsigned *key1, unsigned *key2)
that has achieved the goal of converting a provided string into binary and trimmed off the leading zero. I have assigned my key1 and key2 pointers to the correct indexes. But then, when I return to the main function the values are all lost.
I believe that the problem is that when I pass the *key1/*key2 pointers to the function it only receives a copy of them. But, as I am new to C, I don't know how to fix it?
I created a for loop to help me test/debug.
#include <stdio.h>
#include <string.h>
void binary_and_trim(char *password, unsigned *key1, unsigned *key2);
unsigned int get_n_bits(unsigned *bits, int width, int index);
int main(int argc, const char * argv[]) {
unsigned *key1 = NULL;
unsigned *key2 = NULL;
binary_and_trim("password", key1, key2);
//This test fails with a EXC_BAD_ACCESS error
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %u key2[%d] %d\n", i, key1[i], i, (key2 + i));
}
}
void binary_and_trim(char *password, unsigned *key1, unsigned *key2){
char c;
int count = 0;
unsigned tmp;
unsigned long len = strlen(password);
unsigned trimmedbinary[len * 7];
for(int i = 0; i < len; i++){
c = *(password + i);
for( int j = 6; j >= 0; j--) {
tmp = 0;
if(c >> j & 1){
tmp = 1;
}
*(trimmedbinary + count) = tmp;
count++;
}
}
key1 = trimmedbinary;
key2 = &trimmedbinary[28];
//This test works correctly!!!
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %d key2[%d] %d\n", i, *(key1 + i), i, *(key2 + i));
}
}
I believe that the problem is that when I pass the *key1/*key2 pointers to the function it only receives a copy of them.
Yes, exactly. Pointers are just integers and integers get copied. You solve this with a pointer to a pointer, a "double pointer".
However, there is another problem. trimmedbinary is using stack/automatic memory. "Automatic" meaning it will be freed once the function exits. Once the function returns key1 and key2 will point at freed memory. trimmedbinary must be declared in heap/dynamic memory with malloc.
void binary_and_trim(char *password, unsigned int **key1, unsigned int **key2){
unsigned int *trimmedbinary = malloc(len * 7 * sizeof(unsigned int));
...
*key1 = trimmedbinary;
*key2 = &trimmedbinary[28];
for(int i = 0 ; i < 28; i++) {
printf("key1[%d] %u, key2[%d] %u\n", i, (*key1)[i], i, (*key2)[i]);
}
return;
}
And call it as binary_and_trim("password", &key1, &key2);
Update: I answered the question about how to alter the pointer value, but I have not noticed the memory issue in the code. Please refer to this answer instead.
Pointers are variables themselves. You may already know that with a pointer, you can change the value stored in the variable the pointer points to. Therefore, you need to use a pointer to a pointer to change the value (the memory address) stored in the pointer.
Change your function signature to:
void binary_and_trim(char *password, unsigned **key1, unsigned **key2)
Call with:
binary_and_trim("password", &key1, &key2);
and replace key1 and key2 to *key1 and *key2 in the function definition.
Your problem is that the variable you use to fill with your keys data trimmedbinary is allocated only for the scope of the function binary_and_trim. That said, when you print inside the function
void binary_and_trim(char *password, unsigned **key1, unsigned **key2){
...
unsigned trimmedbinary[len * 7]; // <--
...
*key1 = trimmedbinary; // <--
*key2 = &trimmedbinary[28]; // <--
//This test works correctly!!!
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %d key2[%d] %d\n", i, *(key1 + i), i, *(key2 + i));
}
}
it just works because the data your key1 pointer is trying to access is still there.
However, when you return from your function back to main, key1 and key2 still point back to the buffer you initialized inside binary_and_trim, which is no longer valid because is out of scope.
I suggest you create a buffer in main and pass it as a parameter,
int main(int argc, const char * argv[]) {
const char* password = "password";
unsigned long len = strlen(password);
unsigned buffer[len * 7]; // <-- Add buffer here
unsigned *key1 = NULL;
unsigned *key2 = NULL;
binary_and_trim(password, &key1, &key2, &buffer, len * 7);
//This test succeeds
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %u key2[%d] %d\n", i, key1[i], i, (key2 + i));
}
}
void binary_and_trim(char *password, unsigned **key1, unsigned **key2, unsigned** buffer, size_t buff_size){
char c;
int count = 0;
unsigned tmp;
...
//Use *buffer instead of trimmedbinary
//Check if buff_size matches len(password) * 7
or alternatively, make the buffer heap allocated (dont forget to free() later).
I believe that the problem is that when I pass the *key1/*key2
pointers to the function it only receives a copy of them.
Already altered in code as well.
Wow! Thank you EVERYONE! I finally got it up and running (after 4 hours of beating my head against the wall). I can't begin to say how clutch you all are.
I'm realizing I have tons to learn about the granular memory access of C (I'm used to Java). I can't wait to be an actual WIZARD like you all!

how to convert a int variable to char *array in C with malloc?

I'm doing a school project and this problem came up.
by the way, i can't use library.
How to convert a int variable to char array?
I have tried this but it didn't work, tried a lot of other things and even magic doesn't work...
char *r = malloc(sizeof(char*));
int i = 1;
r[counter++] = (char) i;
Can someone help me?
Thank you for your time.
In your code, you should allocate for char size and not char *. Please try with this code segment
char *r = malloc(sizeof(char) * N); // Modified here
int i = 1;
r[counter++] = i & 0xff; // To store only the lower 8 bits.
You could also try this:
char *r = malloc(sizeof(char));
char *s = (char*)&i;
r[counter++] = s[0];
This is an other funny way to proceed and it allows you to access the full int with:
s[0], s[1], etc...
Do you mind losing precision? A char is generally 8 bits and an int is generally more. Any int value over 255 is going to be converted to its modulo 255 - unless you want to convert the int into as many chars as is takes to hold an int.
Your title seems ot say that, but none of the answers give so far do.
If so, you need to declare an array of char which is sizeof(int) / sizeof(char) and loop that many times, moving i >> 8 into r[looop_var]. There is no need at all to malloc, unless your teacher told you to do so. In whch case, don't forget to handle malloc failing.
Let's say something like (I am coding this w/o compiling it, so beware)
int numChars = sizeof(int) / sizeof(char);
char charArry[numChard]; // or malloc() later, if you must (& check result)
int convertMe = 0x12345678;
int loopVar;
for (loopVar = 0; loopvar < numChars)
{
charArry[loopVar ] = convertMe ;
convertMe = convertMe >> 8;
}
If you can't use the library, you can't use malloc.
But this will work:
int i = 0;
char *p = (char *)&i;
p[0] = 'H';
p[1] = 'i';
p[2] = '!';
p[3] = '\0';
printf("%s\n", p);
Assuming your int is 32bit or more (and your char is 8).
It then follows that if you have:
int i[100];
You can treat that as an array of char with a size equal to sizeof (i). i.e.
int i[100];
int sz = sizeof(i); // probably 400
char *p = (char *)i; // p[0] to p[sz - 1] is valid.
You can use a union instead. Assuming that sizeof int == 4,
typedef union {
int i;
char[4] cs;
} int_char;
int_char int_char_pun;
int_char_pun.i = 4;
for (int i = 0; i < 4; i++) {
putchar(int_char_pun.cs[i]);
}
Be careful; int_char.cs usually won't be a null-terminated string, or it might be, but with length < 4.
if you don't want to include the math library:
unsigned long pow10(int n);
void main(){
char test[6] = {0};
unsigned int testint = 2410;
char conversion_started = 0;
int i=0,j=0;float k=0;
for(i=sizeof(test);i>-1;i--){
k=testint/pow10(i);
if(k<1 && conversion_started==0) continue;
if(k >= 0 && k < 10){
test[j++]=k+0x30;
testint = testint - (k * pow10(i));
conversion_started=1;
}
}
test[j]=0x00;
printf("%s",test);
}
unsigned long pow10(int n){
long r = 1;
int q = 0;
if(n==0) return 1;
if(n>0){
for(q=0;q<n;q++) r = r * 10;
return r;
}
}
NOTE: I didn't care much about the char array length, so you might better choose it wisely.
hmm... what is wrong with the code below
char *r = malloc(sizeof(char) * ARR_SIZE);
int i = 1;
sprintf(r,"%d",i);
printf("int %d converted int %s",i,r);
will it now work for you

Bitwise Operations C on long hex Linux

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.

How to do reverse memcmp?

How can I do reverse memory comparison? As in, I give the ends of two sequences and I want the pointer to be decremented towards the beginning, not incremented towards the end.
There's no built-in function in the C standard library to do it. Here's a simple way to roll your own:
int memrcmp(const void *s1, const void *s2, size_t n)
{
if(n == 0)
return 0;
// Grab pointers to the end and walk backwards
const unsigned char *p1 = (const unsigned char*)s1 + n - 1;
const unsigned char *p2 = (const unsigned char*)s2 + n - 1;
while(n > 0)
{
// If the current characters differ, return an appropriately signed
// value; otherwise, keep searching backwards
if(*p1 != *p2)
return *p1 - *p2;
p1--;
p2--;
n--;
}
return 0;
}
If you something high-performance, you should compare 4-byte words at a time instead of individual bytes, since memory latency will be the bottleneck; however, that solution is significantly more complex and not really worth it.
Much like in a post (C memcpy in reverse) originally linked by Vlad Lazarenko, here is a solution based on that, that I haven't yet tested but should get you started.
int reverse_memcmp(const void *s1, const void *s2, size_t n)
{
unsigned char *a, *b;
a = s1;
b = s2;
size_t i = 0;
// subtracting i from last position and comparing
for (i = 0; i < n; i++) {
if (a[n-1-i] != b[n-1-i]) {
// return differences between different byte, strcmp()-style
return (a[n-1-i] - b[n-1-i]);
}
}
return 0;
}
All you need to do is specify your two ends and the size that you'd like to compare, as well as a step size. Please note especially that the step size may be the most important part for getting the expected results. It will greatly ease the implementation if you restrict the sizes. For the size of a char you could do something like:
int compare (void *one, void *two, size_t size)
{
char *one_char = (char *)one;
char *two_char = (char *)two;
size_t i;
for (i = 0; i < size; i++)
{
if (*(one_char - i) != *(two_char - i))
return(NOT_EQUAL);
}
return(EQUAL);
}
shorter code (C code doesn't need force pointer type cast):
int reverse_memcmp(const void *end1, const void *end2, size_t n) {
const unsigned char *a = end1, *b = end2;
for (; n; --n)
if (*--a != *--b) return *a - *b;
return 0;
}

Check if char array[] contains int, float or double value and store value to respective data type

In C programming, how do i check whether char array[] contains int, float or double value and also store the value using respective data type?
Example:
If the char array[] contains 100 - its int value and should be store in int a.
if the char array contains 10000.01 its float value and should be stored in float b.
The only way you can store mixed types in an array is to have an array of pointers.
You'd need to use a struct or a union to store each one too like so:
#define TYPE_INT 1
#define TYPE_FLOAT 2
#define TYPE_STRING 3
typedef struct {
int type;
void *ptr;
} object;
object* mkobject( int type, void * data ){
object * obj = (object*)malloc(COUNT*sizeof(object))
obj->type = type;
obj->ptr = data;
return obj;
}
No using the above you can store type information
void * intdup( int original ) {
int * copy = (int*) malloc(1*sizeof(int));
*copy = original;
return (void*) copy;
}
void * floatdup( float original ) {
float * copy = (float*) malloc(1*sizeof(float));
*copy = original;
return (void*) copy;
}
int COUNT = 3;
objects** objectlist = (object**)malloc(COUNT*sizeof(object*))
// -- add things to the list
int a_number = 2243;
float a_float = 1.24;
char* a_string = "hello world";
objectlist[0] = mkobject( TYPE_STRING, strdup(a_string) );
objectlist[1] = mkobject( TYPE_INT, intdup(a_number) );
objectlist[2] = mkobject( TYPE_FLOAT, intdup(a_float) );
// iterate through a list
for ( int x = 0; x < COUNT; x++ ){
switch( objectlist[x]->type ){
case TYPE_STRING:
printf("string [%s]\n",(char*) objectlist[x]->ptr );
break;
case TYPE_FLOAT:
printf("float [%f]\n", *(float*) objectlist[x]->ptr );
break;
case TYPE_INT:
printf("int [%d]\n", *(int*) objectlist[x]->ptr );
break;
default;
printf("unintialized object\n");
break;
}
}
In C, unlike in other languages, you have to define the type of the variable at compile time. So if you have a char variable (or char array), you have char and not int and not float and not double.
Since it is not possible to define variables types at run-time, you would still need to have variables of the correct data type defined at compile time. If that is not a problem, you could probably scan the string and look for decimal separators to determine if it is a float or integer value. But perhaps not the most robust method :-)
I think you want to use a union (from my understanding of your answer).
union {
char a[4];
float b;
int c;
} dude;
// ...
union dude woah;
woah.a = "abc";
puts(a);
woah.b = 4.3;
printf("%f\n", woah.b);
woah.c = 456;
printf("%d\n", woah.c);
If you are storing a value like:
"100.04"
in the char array or something like that you can do this to check if the number has a decimal or not:
double check = atof(theChar);
if (check % 1 > 0) {
//It's a real number
}
else {
//It's more specifically an integer
}
If that is what you mean. Your question is a little unclear to me.
Although, this isn't really type checking, it is just testing where the thing has a decimal or not... Like others have said you can't do it because the char* is defined during compilation not during run time and can't be change.
Assume the number is a floating point number and use strtod().
If the conversion worked, the number can be integer. Check limits and closeness to a proper integer and convert again if ok.
Pseudo-code
char *input = "42.24";
char *err;
errno = 0;
double x = strtod(input, &err);
if (errno == 0) {
/* it's (probably) a floating point value */
if ((INT_MIN <= x) && (x <= INT_MAX)) {
if (fabs(x - (int)x) < 0.00000001) {
/* It's an integer */
int i = x;
}
}
} else {
/* deal with error */
}

Resources