How to convert from byte array to word array in c - c

Using c, I have defined a byte and word as follows:
typedef unsigned char byte;
typedef union {
byte b[4];
unsigned long w;
} word;
This allows me to easy go from words to bytes, but I'm not sure of a good way to go the other way. Is it possible to do something like cast from byte* to word* or do I have to stick with iteratively copying bytes to words?

One of the great and terrible things about c is you can take a void pointer and cast it to anything. As long as you know what you are doing it will work, but not something you want to get in the habit of.

const byte input[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
unsigned long output[sizeof(input) / sizeof(unsigned long)];
memcpy(output, input, sizeof(input));

Related

inspecting a buffer through struct

I am novice on the topic, I have unsinged char *buffer
I am trying to inspect it at 3 bytes at a time
I think maybe this can be solved with a 2 dimensional array.
so I tried this -
unsigned char *bytes[3] = {};
*bytes = buffer;
but I see that's a notation to create array of 3 elements of type unsigned char *
is there any way to achieve this without having to memcpy
any pointers are greatly appreciated.
this approach seems to work
typedef struct utf8 {
unsigned char bytes[3];
};
typedef struct utf8 utf8x;
utf8x *xx = (utf8x *) buffer; //buffer is a return from fread (unsinged char *)
if (xx->bytes[0] == 0xe0) {
printf("scratch");
}
however I am still trying to figure out how to compare all the bytes, I guess if I cast xx->bytes to return 3 bytes it should work.
You want to compare three bytes of a buffer at once. You can do this using memcmp() (which a good compiler will optimize out so there is no actual function call). For example:
utf8x *xx = (utf8x *) buff;
if (memcmp(&xx->bytes[0], "\100\50\10", 3) == 0) {
printf("scratch");
}
That will print scratch if the first three bytes are \100 \50 \10.

How to read unsigned char from a socket

I have to receive a UDP packet from the socket. In this packet hour, min and sec are sent as UNSIGNED CHAR. When I receive it in a char[] and put in TextBox for displaying it is not displaying the actual data which are sent, but different values.
char buffer[10];
udpSocketRxCDP->readDatagram(buffer, sizeof(buffer));
ui->textEditsec->setText(buffer[2]);
Please suggest how I can get the actual data.
When you read from a socket, you are reading raw data. If you read it into a char[] buffer and use it as-is then the data is going to be interpreted as char. So either typecast the data to unsigned char when needed:
ui->textEditsec->setText( (unsigned char) buffer[2] );
Or define a suitable struct and typecast to that instead:
struct mypkt
{
unsigned char hour;
unsigned char minute;
unsigned char second;
...
};
ui->textEditsec->setText( ((mypkt*)buffer)->second );
Either way, assuming setText() actually expects a char* string as input, then use sprintf() or similar function to format a string:
char str[12];
sprintf(str, "%d", (int) ((mypkt*)buffer)->second);
ui->textEditsec->setText(str);
With the little given information, you might want to explicitly convert unsigned char to char.
Consider that some data may get corrupted. However, unless you really need it, you can send the data directly as signed char. We can't know whether it's a good choice or not though.

Doubts in the strcpy function used

I am using two buffers which are of unsigned char and when I used the function strcpy, there is a compilation error which says "invalid conversion of unsigned char * to char *". Can anyone please tell me what difference does an unsigned buffer vs. signed buffer makes to the output? This is the program which I had tried.
main()
{
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
strcpy(buff,dst);
printf("The string is %s\n",buff);
}
Now when i typecast the parametrs passed in strcpy to (char *),This programe works fine as shown below
main()
{
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
strcpy((char *)buff,(char *)dst);
printf("The string is %s\n",buff);
}
2nd Question: Does typecasting to char* in the string function create any issues?
Please do let me know if you need any more inputs.
You can just change:
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
to
char buff[20] = "Michael";
char dst[20] = "Jackson";
To think of it logically, A string cannot be signed or unsigned, it is not a numeric value to be treated that way, it is just an char array and you should declare and use it so.
Why do you get the error?
strcpy has the prototype:
char *strcpy(char *restrict s1, const char *restrict s2);
And what you are passing to it is, unsigned char*, when a function is called parameter type checking takes place and the compiler finds that you are not calling the function with proper type parameters and hence it complains about it, When you apply a cast the function arguments match and hence compilation passes.
Does typecasting to char in the string function create any issues?*
No, in this case it doesn't.
Though it makes more sense to change your usage of unsigned char for the reasons mentioned above in the answer.
Suggestion:
Strcpy is not safe, so you are much better off using strncpy, it allows you to explicitly specify how many characters to copy, rather than rely on null terminator of the source string, Also this helps avoiding buffer overflow since you explicitly specify a length.
The way you are using it should be fine.
But you shouldn't use unsigned char arrays with string handling functions. In C strings are char arrays, not unsigned char arrays. Since passing to strcpy discards the unsigned qualifier, the compiler warns.
As a general rule, don't make things unsigned when you don't have to.
strcpy wants char *'s, plain and simple. Cast your buffers to char *'s and you'll be fine. Then there's the whole safety problem with using strcpy in the first place...

Passing values to a function in C

I am new to C and working on it since two months. I have a structure shown below:
struct profile_t
{
unsigned char length;
unsigned char type;
unsigned char *data;
};
typedef struct profile_datagram_t
{
unsigned char *src;
unsigned char *dst;
unsigned char ver;
unsigned char n;
struct profile_t profiles[MAXPROFILES];
} header;
header outObj;
Now the values inside the elements of the structure are read as outObj.src[i], outObj.dst[i], and outObj.profiles[i].type.
Now I want to call a function and pass the values read by me to a function which is actually a Berkeley DB.
void main()
{
struct pearson_record {
unsigned char src[6];
unsigned char dst[6];
unsigned char type;
};
DB *dbp;
int ret;
if ((ret = db_create(&dbp, dbenv, 0)) !=0)
handle_error(ret);
if ((ret = dbp->open(dbp, NULL, "pearson.db", NULL, DB_BTREE, DB_CREATE, 0600)) !=0)
handle_error(ret);
const DBT *pkey;
const DBT *pdata;
struct pearson_record p;
DBT data, key;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
memset(&s, 0, sizeof(struct pearson_record));
Now the above code is written by looking at a example from the DB reference guide. but i don't understand what is const DBT. Also they have added the value inside structure using memcopy which I know is the right way, but now I want to memcopy the values passed which are mentioned above and store them in the structure pearson_record. How should I go with this?? Any kind of help would be appreciated.
Please post the complete code. You mention "they memcopy" (which I assume you refer to memcpy), but all I see is a bunch of memset(*,0). Hope you're not confusing them.
Also "they have added the value inside structure using memcopy which I know is the right way" is not entirely true. It's not necessarily wrong, BUT... char* is basically interpreted as a C string. that is an array of bytes which represent characters which MUST be null terminated (that is the last character must be 0, equivalent to '\0'). The proper way to copy strings is using strcpy() (or strcpy_s on windows), the difference is memcpy is faster and used in other situations (such as pointers\buffer management).
unsigned char* is not so used (at least I never saw it till now). As a note read about char, unsigned char, signed char, char[] and char* (not that it changes your code in any way, but just to make sure you understand the differences).
As for copying data, I assume you mean src, dst and type from pearson_record to header, correct ? If so, for the sake of simplicity I wanted to suggest memcpy but you say that each element is accessed as [i]. Does that mean header.src is an array of more than one pearson_record.src or does header.src[i] correspond to pearson_record.src[i] ? This is slightly unclear to me.
There is a difference between char* src and char* *src.

Copying between byte array and unsigned long

What's the best/recommended way to copy data between a byte array and an integer in C? Currently I'm using memcpy, which doesn't feel right to me. A sample of the sort of thing I'm doing is below.
struct alpha {
unsigned char byte_array[20];
}
void function(struct alpha *st) {
unsigned long num;
/* Do some stuff */
memcpy(st->byte_array, &num, sizeof(unsigned long));
/* Do more stuff */
memcpy(&num, st->byte_array, sizeof(unsigned long));
}
I assume I want to use casts somehow, but I'm not confident of how casting and pointer (de)referencing interacts, particularly when arrays get involved.
memcpy is the standard and portable tool for that effect. Modern optimized compilers will inline this call to something well adapted to your situation, e.g data types, allignement, size (if known at compile time), processor... So I think you should definitively stick to that and not mess around with some handmade optimizations.
It looks exactly the right way to me. Which is to say, when I had to do this, it was the way I did it.
Here's how to do it with casts:
/* Do some stuff */
*(unsigned long *)st = num;
/* Do more stuff */
num = *(unsigned long *)st;
You're casting your struct pointer to a pointer to an unsigned long, then dereferencing the pointer in the assignment statements.
It is not wrong, unless you know that "who" wrote the data into the array wrote them in an endianness different from the one used on your system. Say, e.g., if those data come from a "stream" sent by "someone" over the net. Then, if the protocol uses the so called "network byte order" (namely big endian), and your machine is not big endian, then you obtain wrong values.
Is there any particular reason you need to copy instead of just aliasing the two? e.g.:
union XXX {
char byte_array[20];
unsigned long num;
};
In theory, you don't get defined results when you write to one member of the union then read from the other member. In reality, there's essentially no possibility of getting anything different from what you're getting now -- except (of course) that you don't have to copy data to get from one view to the other -- you just use x.num to look at it as an unsigned long, and x.byte_array to look at it as an array of bytes.
memcpy is the safest way to do this sort of thing. If speed matters though, you can do some cast magic to let the compiler handle the copy natively for you:
*((unsigned long *)&st->byte_array[0]) = num;
num = *((unsigned long *)&st->byte_array[0]);
Both these will use built in register type copies instead of a function call of 4 bytes. If you want to read further into the byte_array, you must be careful of byte alignment issues with this though.
I prefer some default functions for this requirement,
for string to integer
int atoi ( const char * str );
and
for integer to string
char * itoa ( int value, char * str, int base );
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned long int number;
unsigned char string[256];
printf ("Enter a number: ");
fgets ( string, 256, stdin );
number = atoi (string);
printf("number = %d\n",number);
//converting int to string
itoa (number,string,10); //10 is base here for decimal, 16 is used for Hex and 2 for Binary
printf ("string = %s\n",string);
return 0;
}
as per me atoi() function is fine. But in case you don't want to use itoa() or it is not available to you then you can just use sprintf()
sprintf (string,"%ld",number);
I hope it helps
Thanks
Alok.kr.

Resources