Briefly, my problem is: I'm building a dynamic memory manager, which contains various different kinds of objects. I'm marking each different kind of object with a tag, and, to make memory debugging easier, I want those tags to appear in memory as four-byte strings of stuff I can read. However, to efficiently switch on those values, I also want to consider them as unsigned 32 bit integers.
Currently the definition of the objects looks like this:
/**
* an object in cons space.
*/
struct cons_space_object {
char tag[TAGLENGTH]; /* the tag (type) of this cell */
uint32_t count; /* the count of the number of references to this cell */
struct cons_pointer access; /* cons pointer to the access control list of this cell */
union {
/* if tag == CONSTAG */
struct cons_payload cons;
/* if tag == FREETAG */
struct free_payload free;
/* if tag == INTEGERTAG */
struct integer_payload integer;
/* if tag == NILTAG; we'll treat the special cell NIL as just a cons */
struct cons_payload nil;
/* if tag == REALTAG */
struct real_payload real;
/* if tag == STRINGTAG */
struct string_payload string;
/* if tag == TRUETAG; we'll treat the special cell T as just a cons */
struct cons_payload t;
} payload;
};
Tags are four character string constants, e.g.:
#define CONSTAG "CONS"
What I want to be able to so is something like
switch ( cell.tag) {
case CONSTAG : dosomethingwithacons( cell);
break;
But of course you can't switch on a string. However, as these are four byte strings, they could be read in memory as 32 bit unsigned ints. What I want is a macro which, given a string as argument, returns an unsigned int. I've tried
/**
* a macro to convert a tag into a number
*/
#define tag2uint(tag) ((uint32_t)*tag)
but what it in fact does is return as a number the ASCII value of the first character at that address - that is,
tag2uint("FREE") => 70
which is the ascii code for 'F'.
Anyone solve this for me? It's twenty years since I wrote anything serious in C.
#define tag2uint(tag) ((uint32_t)*tag)
means "dereference tag (get 'F' in your example), then convert it to uint32_t."
What you want to do should be
#define tag2uint(tag) (*(uint32_t*)tag)
this means "treat tag as pointer to uint32_t, then dereference it."
Related
I'm in trouble with reading a data from a csv-file and parsing it into a struct. I think its best to show some code.
This is my struct:
typedef struct MyStruct{
char text[150];
char attr[4][50];
char check;
short int num;
} t_mystruct;
A sample line in my file could look like this: This is a long text;brown;green;yellow;silent;X;13;
Now I want to read that file and add that data to an array:
list = malloc(sizeof(t_mystruct) * LIST_SIZE); /* Allocating Memory */
for (i = 0; i < LIST_SIZE; i++) /* Adding data to list */
{
t_mystruct element;
if (fscanf(fp, "%149[^;];%49[^;];%49[^;];%49[^;];%49[^;];%49[^;];%[^;];%d;", &element.text, &element.attr[0], &element.attr[1], &element.attr[2], &element.attr[3], &element.check, &element.num) != 7)
break; /* Break ==> Incomplete line/data */
list[i] = element; /* Add to list */
}
This works, but I face two problems:
The "num" value isn't the same value as in my file. I get results from 49 up to around 13000, but they never match my actual input value (13 in my example).
The code belongs to a "readFile" function. At the end of that function, I face a "stack around the variable "element" was corrupted" error. Edit: When debugging, I can continue and the program works as expected.
But I can't see my mistakes.
You have specified five format specifiers of
%49[^;];
but your struct has only four, and you only provide four arguments to match. You are also reading the last value as int, when it is short.
I am currently attempting to create a buffer that holds data that will later be passed via out the system via a output interface. This interface accepts up to 256 bytes of data. The goal of this data structure is the following:
The array needs to be readable in its entirety from a single pointer. (In this case Buffer start)
It should have a fixed number of header bits that will lead every buffer. (This is the part I am struggling on)
You should be able to add data to the structure without indexing (using the buffer_current)
You should be able to tell if the buffer if full quickly (comparing buffer_current with buffer end)
Below is my code.
typedef struct
{
int TT1;
int TT2;
int Source;
int Data;
} Captured_data;
typedef struct
{
void *Buffer_start;
void *Buffer_current;
void *Buffer_end;
} Message_buffer;
void MB_init(Message_buffer *Message_buffer, int Elements)
{
Message_buffer -> Buffer_start = (Captured_data *)malloc(sizeof(Captured_data)*Elements+2);
Message_buffer -> Buffer_current = Message_buffer -> Buffer_start+2;
Message_buffer -> Buffer_end = Message_buffer + sizeof(Captured_data)*Elements+2;
}
I want to add 2 bytes to the start of this buffer that are 0xAAAA. My initial reaction is to add a Header_length constant and then add Header_length to the input to malloc. From that point I don't know how to assign a value to those two bytes.
Edit: The meat of the question is how do I assign the first two bits of the Messagebuffer within the initialization function.
One final question, if I want Buffer_start to be read out as an array of Char should I assign that point like so:
Message_buffer -> Buffer_start = (char *)malloc(sizeof(Captured_data)*Elements);
This would mean I was allocating an array of Char of size (sizeof(Captured_data*Elements). Then use memcpy to load values directly into buffer based on what Buffer_current is pointing to.
I'm trying to compose a string (char array exactly) containing a fixed 14 starting characters and ending with varying content. The varying bit contains 2 floats and 1 32-bit integer that's to be individually treated as 4 1-byte characters in the array separated by commas. It can be illustrated by the following piece of code, which doesn't compile for some obvious reasons (*char can't assign to *float). So, what can I do to get around it?
char *const comStr = "AT+UCAST:0000=0760,0020,0001\r"; // command string
float *pressure;
float *temperature;
uint32_t *timeStamp;
pressure = comStr + 14; // pressure in the address following the '=' in command string
temperature = comStr + 18; // temperature in the address following the 1st ',' in command string
timeStamp = comStr + 22; // time stamp in the address following the 2nd ',' in command string
I have an unclear memory about something like struct and union in the C language which reserves strictly the memory allocation order in which the variables are defined within the "structure". Maybe something like this:
typedef struct
{
char[14] command;
float *pressure;
char comma1;
float *temperature;
char comma2;
uint32_t *time_stamp;
char CR;
}comStr;
Does this structure guarantee that comStr-> command[15] gives me the first/last byte (depends on the endian) of *pressure? Or is there any other special structure do the trick hiding from me?
(Note: comStr-> command[15] isn't going to be evaluated in future code, so exceeding index boundary is not a concern here. The only important thing here is just whether the memory is allocated continuously so that a hardware fetch lasting for 29 bytes starting from the memory address (comStr-> command) gives me exactly the string I want).
p.s. As I am writing this, I came up with an idea. Can I possibly just use memcpy() for the purpose ;) memcpy has parameters of void* type, hopefully it works! I am going to try it now! All hail stackOverflow anyway!
EDIT: I should have made myself clearer, sorry for any misleading and misunderstanding! The character array I want to construct is to be sent through UART byte by byte. To do this, a DMA system is to be used to transfer the array to the transmit buffer byte by byte automatically if the character array's starting memory address and length are given to the DMA system. So the character array must to be stored continuously in the memory. I hope this makes the question clearer.
This proposed structure:
typedef struct
{
char[14] command;
float *pressure;
char comma;
float *temperature;
char comma;
uint32_t *time_stamp;
char CR;
}comStr;
Is not going to help you with your requirement:
The only important thing here is just whether the memory is allocated continuously so that a hardware fetch lasting for 29 bytes starting from the memory address (comStr->command) gives me exactly the string I want.
Note you can't have two members with the same name; you'd need to use comma1 and comma2 for example. Also, the array dimension is in the wrong place.
One problem is that there will be padding bytes within the structure.
Another problem is that the pointers will be holding addresses of something outside the structure (since there is nothing valid inside the structure for them to point at).
It is not clear what you're after. Only a very limited range of floating point values can be represented by 4 bytes in a string. If you're after binary data I/O, then you can drop the pointers and the commas:
typedef struct
{
char command[14];
float pressure;
float temperature;
uint32_t time_stamp;
}comStr;
If you want the commas present, then you're going to have to work harder:
typedef struct
{
char command[14];
char pressure[4];
char comma1;
char temperature[4];
char comma2;
char time_stamp[4];
char CR;
} comStr;
You will have to load the data carefully:
struct comStr com;
float pressure = ...;
float temperature = ...;
uint32_t time_stamp = ...;
assert(sizeof(float) == 4);
...
memmove(&com.pressure, &pressure, sizeof(pressure));
memmove(&com.temperature, &temperature, sizeof(temperature));
memmove(&com.time_stamp, &time_stamp, sizeof(time_stamp));
You have to unpack with a similar set of memory copies. Note that you won't be able to use simple string manipulation on the structure; there could be zero bytes in any or all of the pressure, temperature and time_stamp sections of the structure.
Structure padding
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
typedef struct
{
char command[14];
float *pressure;
char comma1;
float *temperature;
char comma2;
uint32_t *time_stamp;
char CR;
} comStr;
int main(void)
{
static const struct
{
char *name;
size_t offset;
} offsets[] =
{
{ "command", offsetof(comStr, command) },
{ "pressure", offsetof(comStr, pressure) },
{ "comma1", offsetof(comStr, comma1) },
{ "temperature", offsetof(comStr, temperature) },
{ "comma2", offsetof(comStr, comma2) },
{ "time_stamp", offsetof(comStr, time_stamp) },
{ "CR", offsetof(comStr, CR) },
};
enum { NUM_OFFSETS = sizeof(offsets)/sizeof(offsets[0]) };
printf("Size of comStr = %zu\n", sizeof(comStr));
for (int i = 0; i < NUM_OFFSETS; i++)
printf("%-12s %2zu\n", offsets[i].name, offsets[i].offset);
return 0;
}
Output on Mac OS X:
Size of comStr = 64
command 0
pressure 16
comma1 24
temperature 32
comma2 40
time_stamp 48
CR 56
Note how large the structure is on a 64-bit machine. Pointers are 8-bytes each and are 8-byte aligned.
Various issues to be a covered in your question. I'll take a shot at some of those issues.
The order of members in a structure is guaranteed to be the same as order you have declared them. But there is a different issue here - padding.
Check this -http://c-faq.com/struct/padding.html and follow other links/questions there
Next thing is that you are mistaken in thinking that something like "125" is an integer or something like "1.25" is a float - it's not - it's a string. i.e.
char * p = "125";
p[0] will not contain 0. It will contain '0' - if the encoding is ASCII, then this will be 48. i.e. p[0] will contain 48 & not 0. p[1] will contain 49 & p[2] will contain 52. It will be something similar for float.
The opposite will also happen.
i.e. if you have at an address and you treat it as a char array - the char array will not contain the float you think it will.
Try this program to see this
#include <stdio.h>
struct A
{
char c[4];
float * p;
int i;
};
int main()
{
float x = 1.25;
struct A a;
a.p = &x;
a.i = 0; // to make sure the 'presumed' string starting at p gets null terminate after the float
printf("%s\n", &a.c[4]);
}
For me, it prints "╪·↓". And this has nothing to do with endianness.
Another thing you need to remember, while assigning values to your structure object - you need to remember that comStr.pressure & comStr.temperature are pointers. You cannot assign values to them directly. You need to either give them the address of an existing float or allocate memory dynamically to which they can point to.
Also are you trying to create the char array or to parse the char array which already exists. If you are trying to create it, a better way to do this will be to use snprintf to do what you want. snprintf uses format specifiers similar to printf but prints to a char array. You can create your char array that way. A bigger question remains - what do you plan to do with this char array you create - that will determine if endianness is relevant for you.
If you are trying to read from the char array you have been given and trying to split into floats and commas and whatever, then one way to do this will be sscanf but may be difficult for your particular string format.
At last, I found an easy way round but I don't know if there is any drawback for this method. I did:
char commandStr[27];
char *commandHeader = "AT+UCAST:0000=";
float pressure = 760.0;
float temperature = 20.0;
uint32_t timeStamp = 0;
memcpy(commandStr, commandHeader, 14);
commandStr[26] = '\r';
memcpy((void*)(comStr+14), (void*)(&pressure), 4);
memcpy((void*)(comStr+18), (void*)(&temperature), 4);
memcpy((void*)(comStr+22), (void*)(&timeStamp), 4);
Does this code have any security issues or performance issues or whatever?
In the hope of gaining a better understanding of the answers
given in this post, can someone please explain to me if the
following circular buffer implementation is possible, and if
not, why not.
#define CB_TYPE_CHAR 0
#define CB_TYPE_FLOAT 1
...
typedef struct CBUFF
{
uint16 total; /* Total number of array elements */
uint16 size; /* Size of each array element */
uint16 type; /* Array element type */
uint16 used; /* Number of array elements in use */
uint16 start; /* Array index of first unread element */
void *elements; /* Pointer to array of elements */
} CBUFF;
...
void cbRead(CBUFF *buffer, void *element)
{
if (buffer->type == CB_TYPE_CHAR)
{
/* The RHS of this statement is the problem */
*(char*)element = *(buffer->elements[buffer->start]);
}
/* Other cases will go here */
buffer->start = (buffer->start + 1) % buffer->total;
--buffer->used;
}
I understand that the LHS must be cast to char so that I can
dereference the void pointer. I also understand that this code
fragment:
buffer->elements[buffer->start]
gives the address of the 'buffer->start' element of the elements
array, which I also want to dereference in order to get to the
content of that address. Or at least that's what I take from
K&R.
Given all that, how do I tell the compiler that the content of
the memory at that address is a char, and that it is okay to
dereference it? There is something going on here I just don't
understand.
buffer->elements is also a void * so you need to cast it before you can do anything with it:
*(char*)element = ((char *)buffer->elements)[buffer->start];
Given all that, how do I tell the compiler that the content of the memory at that address is a char, and that it is okay to dereference it?
Well, you've already done it on the LHS of that line:
*(char*)element = *(buffer->elements[buffer->start]);
To derefence buffer->elements[n] you will need to cast that as well.
*(char*)element = *((char*)buffer->elements)[buffer->start];
Now the question is whether or not that cast is correct. I can't tell you that as you did not post the initialization of buffer->elements.
I have a packet from a server which is parsed in an embedded system. I need to parse it in a very efficient way, avoiding memory issues, like overlapping, corrupting my memory and others variables.
The packet has this structure "String A:String B:String C".
As example, here the packet received is compounded of three parts separated using a separator ":", all these parts must be accesibles from an structure.
Which is the most efficient and safe way to do this.
A.- Creating an structure with attributes (partA, PartB PartC) sized with a criteria based on avoid exceed this sized from the source of the packet, and attaching also an index with the length of each part in a way to avoid extracting garbage, this part length indicator could be less or equal to 300 (ie: part B).
typedef struct parsedPacket_struct {
char partA[2];int len_partA;
char partB[300];int len_partB;
char partC[2];int len_partC;
}parsedPacket;
The problem here is that I am wasting memory, because each structure should copy the packet content to each the structure, is there a way to only save the base address of each part and still using the len_partX.
How about replacing the (:) with a 0, and add a null to the end - then you have three char * to pass around. You will need to deal with 0 length strings, but that might solve it
To avoid corrupting memory and other variables, you generally declare large data buffers as statics and place them at file scope, then allocate a separate RAM segment for them. Having them sitting on the stack is a bad idea in any embedded system.
You need to consider whether there is an alignment requirement for the CPU and whether the code should be portable or not. The compiler is free to add any number of padding bytes anywhere in that struct, meaning you may not be able to do this:
parsedPacket pp;
memcpy(&pp, raw_data, sizeof(parsedPacket )) ;
For this reason, structs are generally a bad choise for storing data packages. The safest solution is this:
/* packet.h */
typedef struct parsedPacket_struct {
uint8_t* partA;
uint8_t* partB;
uint8_t* partC;
uint16_t len_partA;
uint16_t len_partB;
uint16_t len_partC;
}parsedPacket;
#define MAX_PART_A 2
#define MAX_PART_B 300
#define MAX_PART_C 2
void packet_receive (parsedPacket* packet);
/* packet.c */
static uint8 partA[MAX_PART_A];
static uint8 partB[MAX_PART_B];
static uint8 partC[MAX_PART_C];
void packet_receive (parsedPacket* packet)
{
/* receive data from server */
...
packet->len_partA = ...;
packet->len_partB = ...;
packet->len_partC = ...;
packet->partA = partA;
packet->partB = partB;
packet->partC = partC;
memcpy(partA, A_from_server, packet->len_partA);
memcpy(partB, B_from_server, packet->len_partB);
memcpy(partC, C_from_server, packet->len_partC);
}
This can be extended to contain several static buffers if needed, ie a static array of arrays for each buffer. As you are dealing with large amounts of data in an embedded system, you can never allow the program to stack the buffers at a whim. The maximum amount of copies of a received packet must be determined during program design.
I'm not sure why you think your approach is wasting memory, but here's what I would do if I were feeling especially hacky:
typedef struct {
char *a, *b, *c;
char data[1]; // or 0 if your compiler lets you, or nothing in C99
} parsedPacket;
This is called a flexible array member. Basically, when you allocate memory for your struct, you do this:
parsedPacket *p = malloc(offsetof(parsedPacket, data[N]));
N above becomes the amount of data your array needs, i.e. how long the string you read is. This allocates the struct so that the data member has enough size for your entire string of data. Then, copy the string you recieve into this member, replace ':' characters with '\0', and set a to the first string (i.e. p->a = p->data), b to the second (p->b = p->data + strlen(p->a) + 1) and c to the third. Of course, you can make this process easier by doing it all at once:
size_t current = 0;
p->a = p->data;
p->b = p->c = NULL;
while(1)
{
int i = getc();
if(i == '\n' || i == EOF) break; // or whatever end conditions you expect
if(i == ':')
{
p->data[current] = '\0';
++current;
if(p->b == NULL) p->b = &p->data[current];
else if(p->c == NULL) p->c = &p->data[current];
else /* error */;
}
else
{
p->data[current] = i;
}
}
The type of each len_partN should be a type that can count up to the length of partN. E.g.:
typedef struct parsedPacket_struct {
char partA[300];unsigned short len_partA; // unsigned shorts have < 32k distinct values
char partB[300];unsigned short len_partB;
char partC[300];unsigned short len_partC;
}parsedPacket;
This seems like a design decision. If you want the struct to be easy to create, use the above approach, but beware its drawbacks (like "what if B has more than 300 chars?").