Converting unsigned char pointer of data to struct containing ints - c

I am trying to cast this pointer of data to my struct and the actual value populate in the struct.
unsigned char *data = "00000001000000020000000300000004AE93KD93KD91Q830DMNE03KEkdaredgreenblueorangeyellow";
typedef struct mystruc {
int a;
int b;
int c;
int d;
} mystruc;
mystruct ms = (mystruct *)data;
printf("%i", ms->a);
Output:
808464432
I am trying to find out how to fill in a, b, c, d with the actual values 1, 2, 3, 4
I would like the output to be:
1
I will also need to later access the rest of the data.

Use sscanf() to parse the numbers in the string.
mystruct ms;
sscanf(data, "%8d%8d%8d%8d", &ms.a, &ms.b, &ms.c, &ms.d);
%8d means to parse an 8-character decimal field as an int. If it's actually hexadecimal, change it to %8x.
Your code is interpreting the character codes in the string as the binary representation of the structure members, it doesn't parse it.

Your unsigned char is one byte wide, so "00000001" will be 3030303031 in hex, because the ASCII code for '0' is 0x30 in hex, and the ASCII for '1' is 0x31.
Your int is 4 bytes wide, so it'll capture the first 4 bytes of data, which will be 30303030 in hex, or 808464432 in decimal.
This, however, will work on a little-endian machine:
#include <stdio.h>
typedef struct mystruct {
int a;
int b;
int c;
int d;
} mystruct;
unsigned char *data = "\1\0\0\0"; // use octal numbers, not ASCII, also note the reversed order
int main(void) {
mystruct *ms = (mystruct *)data;
printf("%i", ms->a); // outputs: 1
}

Related

use memcpy to fill a struct taking data from an array in C

The following task is from an exam I took in engineering school (mechanical engineering):
You get an array unsigned char buffer[128]; used to read data from a source byte by byte, containing data of the structure:
struct Pixel {
unsigned char x;
unsigned char y;
unsigned char greyValue;
};
The task is: Create an instance of a pixel and copy the data content from the header of the buffer using "memcpy".
My aproach does not seem to work:
#include <stdio.h>
#include <string.h>
struct Pixel {
unsigned char x;
unsigned char y;
unsigned char greyValue;
};
int main()
{
unsigned char buffer[128] = {2,4,44};
struct Pixel singlePixel;
memcpy(singlePixel, buffer, 3);
printf("singlePixel.x = %d\n", singlePixel.x);
printf("singlePixel.y = %d\n", singlePixel.y);
printf("singlePixel.greyValue = %d\n", singlePixel.greyValue);
return 0;
}
I would expect that singlePixel.x = 2, singlePixel.y = 4 and singlePixel.greyValue = 44.
When debugging I get the error: incompatible type for argument 1 of ‘memcpy’
I'm also not at all sure if my approach is up to the task, since I don't understand exactly how this should works with the buffer...

Clear just bit field members of a struct?

I have a struct like the following:
struct Foo {
unsigned int id;
unsigned int flag_1 : 1;
unsigned int flag_2 : 1;
unsigned int flag_3 : 1;
// Some arbitrary number of further flags. Code is
// automatically generated and number will vary.
// Notably, it may be more than an int's worth.
int some_data;
float some_more_data;
// ...
};
From time to time, I need to reset all the flags to zero while preserving the rest of the struct. One way is obviously to set each flag to 0 individually, but it feels like there ought to be a way to do it in one fell swoop. Is that possible?
(Note that I am open to not using bit fields, but this is code that will sometimes run on memory-contrained systems, so the memory savings are very appealing.)
Edit:
There is a similar question here: Reset all bits in a c bitfield
However, the struct in that question is entirely bitfields. I cannot simply memset the entire struct to zero here, and the other answer involving unions is not guaranteed to work, especially if there are more than an int's worth of flags.
Just use a separate struct for the flags:
struct Foo_flags {
unsigned int flag_1 : 1;
unsigned int flag_2 : 1;
unsigned int flag_3 : 1;
// ...
};
struct Foo {
unsigned int id;
struct Foo_flags flags;
int some_data;
float some_more_data;
// ...
};
Or even a simpler nested struct:
struct Foo {
unsigned int id;
struct {
unsigned int flag_1 : 1;
unsigned int flag_2 : 1;
unsigned int flag_3 : 1;
// ...
} flags;
int some_data;
float some_more_data;
// ...
};
Then, later in your code:
struct Foo x;
// ...
x.flags.flag_1 = 1;
// ...
memset(&x.flags, 0, sizeof(x.flags));
With some minor adjustments, you can use the offsetof macro to find the beginning and end of the "flag" data within the structure, then use memset to clear the relevant memory. (Note that you cannot use offsetof directly on bitfields, hence the addition of the flag_beg member!)
Here's a working example:
#include <stdio.h>
#include <stddef.h> // defines offsetof
#include <string.h> // declares memset
struct Foo {
unsigned int id;
unsigned int flag_beg; // Could be unsigned char to save space
unsigned int flag_1 : 1;
unsigned int flag_2 : 1;
unsigned int flag_3 : 1;
unsigned int flag_end; // Could be unsigned char to save space
// Some arbitrary number of further flags. Code is
// automatically generated and number will vary.
// Notably, it may be more than an int's worth.
int some_data;
float some_more_data;
// ...
};
#define FBEG (offsetof(struct Foo, flag_beg))
#define FEND (offsetof(struct Foo, flag_end))
int main()
{
struct Foo f;
f.id = 3; f.flag_1 = 1; f.flag_2 = 0; f.flag_3 = 1;
f.some_data = 33; f.some_more_data = 16.2f;
printf("%u %u %u %u %d %f\n", f.id, f.flag_1, f.flag_2, f.flag_3, f.some_data, f.some_more_data);
memset((char*)(&f) + FBEG, 0, FEND - FBEG);
printf("%u %u %u %u %d %f\n", f.id, f.flag_1, f.flag_2, f.flag_3, f.some_data, f.some_more_data);
return 0;
}

LZW Sequence implementation

I am absolutely lost on what I am supposed to do in this C programming assignment I have. I am pretty sure I created the newSequence function wrong, because there isn't much clarity, for me, on what all the variables mean. Can someone guide me on how I need to create a newSequence?
#include <stdlib.h>
#include "sequencecopy.h"
Sequence* newSequence(unsigned char firstByte, unsigned long long hashSize) {
Sequence *s = malloc(sizeof(Sequence));
s->length = 1; // each letter is one byte
s->code = (unsigned int) firstByte; // casting char input into 4 byte value
s->hash = (unsigned long long) s->code; // casting code into 8 byte value
s->hash = ((s->hash << 5) + s->hash) + s->code; // hash function
s->bucket = s->hash % hashSize; // hash code modded to hash table size
// s->bytes[0] = firstByte;
return s;
}
void deleteSequence(Sequence* sequence) {
free(sequence);
}
Sequence* copySequenceAppend(Sequence* sequence, unsigned char addByte, unsigned int hashSize) {
return NULL;
}
unsigned int outputSequence(Sequence* sequence,
void (*writeFunc)(unsigned char c, void* context), void* context) {
return 0;
}
bool identicalSequences(Sequence* a, Sequence* b) {
return true;
}
This is the header file sequence.h
#ifndef SEQUENCE_H
#define SEQUENCE_H
#include <stdbool.h>
typedef struct _sequence {
unsigned int length; // number of bytes in the sequence
unsigned int usage; // number of times the sequence is used
unsigned int code; // compression code assigned in the dictionary
unsigned int wordCount; // number of words holding the bytes
unsigned long long hash; // raw hash code for the sequence
unsigned long long bucket; // hash code modded to the hash table size
struct _sequence* next; // next sequence in a list of sequences (collisions)
union { // union data permits both character and word accessability
unsigned char bytes[1 << SEQUENCE_ALLOC]; // buffer for characters, multiple of 8
unsigned long long words[1]; // for accessing data as 8 byte words
} data;
} Sequence;
/* create a new, one character Sequence using char firstByte as the character.
hashSize is the size of the hashTable and if non-zero, a hash
is computed for the new Sequence. */
Sequence* newSequence(unsigned char firstByte, unsigned long long hashSize);
/* either frees sequence or places it on a list of idle sequences for possible reuse */
void deleteSequence(Sequence* sequence);
/* creates a new Sequence containing the old sequence bytes with newByte appended to the end,
hashSize has the same meaning and function as in newSequence() above. */
Sequence* copySequenceAppending(Sequence* sequence, unsigned char newByte, unsigned long long hashSize);
/* write the data bytes of sequence to the FILE* fd, return the number of bytes written. */
unsigned int outputSequence(Sequence* sequence,
void (*writeFunc)(unsigned char c, void* context),
void* context);
/* returns true if a and b contain identical sequences of data bytes, false otherwise */
bool identicalSequences(Sequence* a, Sequence* b);
#endif

Define a structure that contains a data array and some pointers to the same data array areas

I want to define a structure that contains a data array and some pointers to the same data array. So I defined the structure and then I initialize the pointer like this:
typedef struct {
unsigned char data[MAX_PACKET_DATA];
unsigned char* sector1;
unsigned char* sector2;
unsigned char* sector3;
} Packet;
[...]
NGSCTransmittingDataPacket packet
[...]
packet->sector1 = packet.data + SECTOR1_OFFSET;
packet->sector2 = packet.data + SECTOR2_OFFSET;
packet->sector2 = packet.data + SECTOR3_OFFSET;
Can I initialize the pointer directly inside the typedef struct definition? If I write
typedef struct {
unsigned char data[MAX_PACKET_DATA];
unsigned char* sector1 = data + SECTOR1_OFFSET;
unsigned char* sector2 = data + SECTOR2_OFFSET;
unsigned char* sector3 = data + SECTOR3_OFFSET;
} Packet;
the compiler gives me error.
Any solution?
you cannot do that, C won't allow it. But in your example you could do that equivalent:
typedef struct {
unsigned char data[SECTOR1_OFFSET];
unsigned char sector1[SECTOR2_OFFSET-SECTOR1_OFFSET];
unsigned char sector2[SECTOR3_OFFSET-SECTOR2_OFFSET];
unsigned char sector3[MAX_PACKET_DATA-SECTOR3_OFFSET];
} Packet;
There's no padding since all members are char arrays.
You normally cannot go further SECTOR1_OFFSET-1 for an index of data, but there it would work (or create an union with a MAX_PACKET_DATA-length array if you want to make it cleaner, because some compilers could complain if you're accessing data with a bigger index)
Example with an union of 2 anonymous structures:
#include <stdio.h>
#define SECTOR1_OFFSET 20
#define SECTOR2_OFFSET 50
#define SECTOR3_OFFSET 80
#define MAX_PACKET_DATA 100
typedef union
{
struct
{
unsigned char sector0[SECTOR1_OFFSET];
unsigned char sector1[SECTOR2_OFFSET-SECTOR1_OFFSET];
unsigned char sector2[SECTOR3_OFFSET-SECTOR2_OFFSET];
unsigned char sector3[MAX_PACKET_DATA-SECTOR3_OFFSET];
};
struct
{
unsigned char data[MAX_PACKET_DATA];
};
} Packet;
int main()
{
Packet p;
p.data[SECTOR3_OFFSET] = 'a';
p.data[SECTOR3_OFFSET+1] = 'z';
p.data[SECTOR3_OFFSET+2] = '\0';
printf("sector 3 %s\n",p.sector3);
return 0;
}
result:
sector 3 az

Judy Array judysl(3) strange behavior

I'm testing the judy arrays implementation on ubuntu 11.10 "libjudy-dev".
I'm encounter with a strange behavior, possible bug. related to the size of val and the key.
In the example, if i use the struct TEST with only 1 int with large keys works, but if i use the 10 int struct with the same key it doesn't, the 10 int struct works ok with small keys.
judy manpage
In the man page said that the string can be any size.
#include <stdio.h>
#include <string.h>
#include <Judy.h>
/*struct TEST {
unsigned int size9;
};*/
struct TEST {
unsigned int size0;
unsigned int size1;
unsigned int size2;
unsigned int size3;
unsigned int size4;
unsigned int size5;
unsigned int size6;
unsigned int size7;
unsigned int size8;
unsigned int size9;
};
int main()
{
struct TEST *val;
char key[1024];
Pvoid_t array = NULL;
//strcpy(key, "0123456789_0123456789");
strcpy(key, "0123456789_0123456789_0123456789");
JSLI(val, array, key);
val->size9 = 10;
val = NULL;
JSLG(val, array, key);
if(val == NULL) {
printf("NULL\n");
} else {
printf("%u\n", val->size9);
}
return 0;
}
JudySL "maps" a string to a word in RAM. This word is used as a "word_t" or a "pointer to more memory". The routines return (val in your case) a pointer to the word available for your use.
Your code makes that pointer (val) a pointer to a struct of greater size than one word -- thus
destroying part of the internal Judy data structure with the statement "val->size9 = 10;".
Keep in mind that the "key" is a string, and the PValue is a pointer to an object of size word. If you want *PValue to point to struct TEST and it is bigger than a word_t then memory must be allocated for it. Your test program seems to want to map a string to a struct TEST--
struct TEST is bigger than a word_t.
Doug Baskins

Resources