I have a structure as follows
typedef struct s_CanMsg
{
uint32_t id;
uint16_t timestamp;
uint8_t data[8];
uint8_t dlc;
bool_t isExtended;
bool_t isRemote;
} s_CanMsg_t;
and I have a structure variable as follows
s_CanMsg_t CANEraseResponse;
Now I am trying to pass an array to the data member of the structure variable as follows:
CANEraseResponse.data[8] = {0x00, 0xFF, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00};
This is showing syntax error and how can I pass the data to the structure variable with array member? Thanks in advance.
You can initialize the whole structure when you define the variable:
s_CanMsg_t CANEraseResponse = {
some_value_for_id,
some_value_for_timestamp,
{0x00, 0xFF, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00},
some_value_for_dlc,
some_value_for_isExtended,
some_value_for_isRemote
};
You can also use a designator to explicitly initialize only the array member;
s_CanMsg_t CANEraseResponse = {
.data = {0x00, 0xFF, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00}
};
Then all other members will be initialized to zero.
And of course you can define a temporary array and copy into the structure array:
static uint8_t data[8] = {0x00, 0xFF, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00},
s_CanMsg_t CANEraseResponse;
memcpy(CANEraseResponse.data, data, sizeof data);
Lastly, if none of the ways above are acceptable, then the only remaining solution is to explicitly assign to each element of the array:
CANEraseResponse.data[0] = 0x00;
CANEraseResponse.data[1] = 0xFF;
CANEraseResponse.data[2] = 0x00;
CANEraseResponse.data[3] = 0x04;
CANEraseResponse.data[4] = 0x02;
CANEraseResponse.data[5] = 0x00;
CANEraseResponse.data[6] = 0x00;
CANEraseResponse.data[7] = 0x00;
The notation you are using can only be used to initialize an array. Once you declare your struct variable, you have moved past initialization. You can, however, do it with something called a "designated initializer" like so:
s_CanMsg_t CANEraseResponse = {.data= {0x00, 0xFF, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00}};
CANEraseResponse.data[8] refers to the 9th element of the data member (as the array is zero based. Try removing the [8].
Edit/Clarification: removing the [8] will not solve your issue, but you should be aware that CANEraseResponse.data[8] points to a position outside of the data array.
You can't assign arrays directly in C. As well as the initialization techniques shown in other answers, you could use a compound literal and memmove() (or memcpy()):
memmove(CANEraseResponse.data, (uint8_t[]){ 0x00, 0xFF, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00 }, sizeof(CANEraseResponse.data));
Related
I have a char *data that is a Datagram to represent the packet I want to send in but I need to insert on that an uint8_t array.
// Datagram to represent the packet
char datagram[4096], source_ip[32], *data, *pseudogram;
// zero out the packet buffer
memset(datagram, 0, 4096);
// IP header
struct iphdr *iph = (struct iphdr *)datagram;
// UDP header
struct udphdr *udph = (struct udphdr *)(datagram + sizeof(struct ip));
// Data part
data = datagram + sizeof(struct iphdr) + sizeof(struct udphdr);
uint8_t packet_bytes[] = { 0xff, 0xff, 0x81, 0x01, 0x01 };
memcpy(data, packet_bytes, 5);
Doing this allows me to insert what I need and it works but the problem is that I have and uint8_t array with 0x00 in the middle making this harder than I thought because the 0x00 hex also means a termination of an array, how can I make it to work with this array instead ?
char packet_bytes[] = {
0xff, 0xff, 0x81, 0x00, 0x00, 0x00, 0x00, 0x30,
0x13, 0x43, 0x00, 0x01, 0x01, 0x01, 0x02, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x06, 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, 0x63,
0x02, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x05,
0x00, 0x00, 0x00, 0x0c, 0x00, 0x09, 0x04, 0x00,
0x0a, 0x00, 0x03, 0x01, 0x00, 0x11, 0x77, 0x25
};
the problem is that I have and uint8_t array with 0x00 in the middle making this harder than I thought because the 0x00 hex also means a termination of an array
There is no such thing as "termination of an array" in C. There is null termination of character arrays used as strings, but that isn't applicable here. So the memcpy part will work just fine.
You have some other problems however:
char datagram[4096], char packet_bytes[] etc
char is unsuitable, dangerous and non-portable for the purpose of holding raw binary data. Use uint8_t instead. See Is char signed or unsigned by default?
struct iphdr *iph = (struct iphdr *)datagram;
This will lead to undefined behavior because of alignment and strict aliasing. What is the strict aliasing rule? You cannot wildly type pun from a character array to another type by pointer casts (though the other way around from "any type" to character type is possible). Furthermore, your struct may contain padding, in which case it is extra non-portable and you don't want to be sending padding bytes around.
(struct udphdr *)(datagram + sizeof(struct ip)); Same problem as above.
The only reliable way to do this is either to disable struct padding and then memcpy in/out of the struct. Or alternatively write serialization/deserialization routines accessing one struct member at a time, moving it to/from the raw data.
I have UInt8 data array which I got from TCPSocket.
I want to read UInt32s and UInt16s from different indices.
For example:
data = UInt8[0xFF, 0x00, 0x00, 0x00, 0xAA, 0x00]
// Something like this:
extracted_UInt32 = data.readUInt32(1) # [1-4]
extracted_UInt16 = data.readUInt16(5) # [5-6]
It is exactly like Node.js's Buffer.readUInt16LE(offset): https://nodejs.org/api/buffer.html#buffer_buf_readint16le_offset
Thanks!
You can read the data as a given type from the buffer:
julia> data = IOBuffer(UInt8[0xFF, 0x00, 0x00, 0x00, 0xAA, 0x00]);
julia> a = read(data, UInt32)
0x000000ff
julia> b = read(data, UInt16)
0x00aa
You can probably do this from the TCP socket directly without materializing as a vector of bytes.
Also I have found reinterpret can be used:
data = UInt8[0xFF, 0x00, 0x00, 0x00, 0xAA, 0x00]
a = reinterpret(UInt32, data[1:4])
b = reinterpret(UInt16, data[5:6])
it seems this code make my display go crazy sometimes (but only sometimes). But when I remove dat=~dat; it seems to work fine.
why?
what I am trying to do here is just make the ascii letters be the oposite: so for example:
11001000 will be:
00110111
or
10101111 would be:
01010000
the reason for doing this is that i want to have one row (the active row) in the diplay window with black on white pixels instead of opostie like the rest of the display window.
Is there some other way I could do this? (invert the numbers)
FYI: I am programing in C. Atmel studio. atmega 4809, SSD1305z display, SPI-simular interface.
void displayinvertedString(char str[], uint8_t ypos,uint8_t xpos)
{
Set_Page_Address(ypos);
Set_Column_Address(xpos);
int len = strlen(str);
uint8_t dat;
int temp;
for (int e=0; e<len; e++)
{
dat = 0xff;
Write_Data(dat); //to get an extra space between the
// numbers/letters for
//making it easier to read the text on the display
temp = str[e];
temp=temp-0x20; // As the lookup table starts from Space(0x20)
for (int w=0; w<5; w++)
{
dat= OledFontTable[temp][w]; // Get the data to be displayed for LookUptable
dat =~ dat;
Write_Data(dat);
}
}
}
----------
static uint8_t OledFontTable[][FONT_SIZE]={
//static uint8_t OledFontTable[] = {
0x00, 0x00, 0x00, 0x00, 0x00, // space
0x00, 0x00, 0x2f, 0x00, 0x00, // !
0x00, 0x07, 0x00, 0x07, 0x00, // "
0x14, 0x7f, 0x14, 0x7f, 0x14, // #
0x24, 0x2a, 0x7f, 0x2a, 0x12, // $
0x23, 0x13, 0x08, 0x64, 0x62, // %
0x36, 0x49, 0x55, 0x22, 0x50, // &
ETC. Etc.
just more raw pixel data here. this part ends like this:
0x00, 0x00, 0xFF, 0x00, 0x00, // |
0x00, 0x82, 0x7C, 0x10, 0x00, // }
0x00, 0x06, 0x09, 0x09, 0x06 // ~ (Degrees)
};
void Write_Data(unsigned char Data)
{
PORTA.OUTCLR = PIN7_bm; //cs
PORTB.OUTSET = PIN2_bm; //dc
Write_Command(Data); //
}
void Write_Command(unsigned char data)
{
SPI0.DATA = data; // copy data to DATA register
while ((SPI0.INTFLAGS & SPI_RXCIF_bm) == 0) ; //wait
}
I have asked a bit about this before. but i thought i would look "cleaner" with a new tread since info was missing from the last one.
It turned out I needed to toggle the chip select (CS) so the clock did not get out of sync with time.
The clock sync drifted with time.
It was going crazy faster for the non inverted data for some reason. But with the normal data it happend after some time also.
Thank you for the answers.
I want to see if this is actually possible in C code.
unsigned char message[] = {0x00,0x00,"Hello world"};
There is some firmware that I want to force to take characters other than 0x00 in the same array. It has:
unsigned char message[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
already written in it. I want it to take other characters since both these are possible:
unsigned char message[] = "Hello world";
unsigned char message2[] = {0x00,0x00,0x00};
I have a buffer that stores letters from a UART which I want to combine with
unsigned char message2[] = {0x00,0x00,0x00};
As the compiler told you, you can't do what you attempted in the way you attempted to do it.
Note that you could use:
unsigned char message[] = "\x00\x00Hello world";
but considerable care is required since:
unsigned char message[] = "\x00\x00Byebye world";
has a second byte containing \xB or \013 and the third byte is y. The hex escape stops at the first character that is not a hexadecimal digit (so "\x00Babaganoush" has six digits in the hex escape; and there are lots of ways of spelling 'Babaganoush').
Let's say I've calloc'd some memory for myself:
byte *header = calloc(5 + ZHEADERSIZE, sizeof(byte));
This gives me an array of 0's. But what if I want to make a custom initialization of the memory? The following code is a fairly detailed initialization for an array literal. Note that it actually contains variables, so I can't just memcpy all of the array over. I'm wondering if I can replicate this style of initialization for a block of memory that is malloc'd out without having to insert them manually.
unsigned char zhead[] =
{
0x00, 37, 0, 218, 0xFF,
0x50, 0x4b, 0x03, 0x04,
0x14,
0x00,
0x00, 0x00,
0x08, 0x00,
0x08, 0x03,
0x64, 0x3c,
0xAA, 0xBB, 0xCC, 0xDD,
csize, (csize>>8), 0, 0,
uncsize, (uncsize>>8), 0, 0,
0x07, 0x00,
0x00, 0x00,
'r', '/', 'r', '.', 'z', 'i', 'p'
};
You cannot initialize dynamically allocated memory in C other than to zero using calloc. You can however provide a static prototype array from which you copy the data:
const char prototype[] = { 'a', 'b', 'c' };
int main()
{
char * data = malloc(sizeof prototype);
memcpy(data, prototype, sizeof prototype);
data[1] = 'z'; // fill in custom data
}