Sida 2 av 3
Postat: 27 december 2008, 17:26:54
av kimmen
Nej, det är ju bara en datatyp som förklarar hur minnesområdet är uppdelat som pekas på av variabler med typen som man just gjorde.
Man måste göra det när man definierar en variabel. I C++ kan man använda en konstruktor dock för att låta structar initiera sig själva.
Postat: 27 december 2008, 17:29:50
av kimmen
Icecap skrev:Det beror faktisk på kompilern.
Generellt är svaret "nej" men vissa kompilers är så att de kan göra det tack vara en kod som körs innan main.
Jag har löst det på det sätt att jag deklarerar en typedef med den önskade struktur, här kallat T_TEST:
typedef struct
{
char Char_1;
char Char_2;
int Int_1;
} T_TEST;
Först deklarerar man dom i RAM:
T_TEST Testvar;
Sedan är det standardinställningen:
const T_TEST Default = {0, 0, 2};
Sedan kopierar man från Default till Testvar på lämpligt sätt, memcpy(&Testvar, &Default, sizeof(Testvar)); kan vara ett av dessa.
Medger kompilern att man kan definiera och initiera RAM-delen utförs dessa steg automatisk innan main aktiveras men jag gillar att ha koll på vad som händer så jag föredrar att göra det själv.
Om jag inte minns fel är "const T_TEST Default = {0, 0, 2};" en C++-grej men vissa kompilatorer låter ju en göra sånt även i C-läge...
Tilldelningen borde dock inte vara något problem att göra Testvar = Default utan problem. Går i alla fall om "const T_TEST Default = {0, 0, 2};" gick.
Postat: 27 december 2008, 17:50:53
av thepirateboy
Jag tänkte snarare om det gick i samband med deklarationen av Unionen i detta exempel:
Kod: Markera allt
typedef struct
{
byte SenderID[8];
byte ReciverID[8];
byte Datatype;
byte Data[16];
byte Length;
} T_RF_Data_Struct; // Totalt 34 bytes
union
{
T_RF_Data_Struct Data;
byte Buffer[34];
} Alla_Bytes_I_Samma_Klump; // Kan jag här sätta SenderID till ett värde??
Testvar = Default verkar annars fungera med avr-gcc, kompilatorn klagar iaf inte på tilldelningen.
Postat: 27 december 2008, 19:41:16
av kimmen
Nej, unionen är också bara en datatyp som förklarar hur minnet är uppdelat. Man måste göra det när man skapar variabler av typen.
Postat: 27 december 2008, 20:08:22
av Icecap
kimmen: nej, ingen C++ grej, fungerar klockrent på minst 3 olika kompilers som jag använder där två inte ens har C++ funktionalitet och den andra inte är i C++-läge.
thepirateboy: Och att deklarera en "union"... då blir det så att man "måste" deklarera dessa konsta värden som en del av vad unionen är uppbyggd av men jag är inte säker på att vi förstår varandra eller rättare: att DU inte riktigt förstår hur det hela fungerar.
Variabler är i RAM, reserverade platser bara, om man deklarerar dom till ett initialt värde måste detta värde överföras från ROM till RAM vid uppstart eller hur?
Detta kan skötas av en programsnudd som körs omedelbart innan main() körs och i så fall är det kompilern som lägger till lite extrakod som fixar problemet, i annat fall får man sköta det själv på det sätt som beskrivs i tidigare inlägg.
Och det är intensivt likgiltigt HUR värdet är deklarerat.
En del kompilers skiter till och med i att man anger vilka värden variablerna initialt ska ha, de tillåter det för att det är legalt i C men den deklaration har inget värde för att värden inte fylls i RAM vid uppstart.
Så mitt råd: testa!
Och sedan får du tänka lite:
union
{
T_RF_Data_Struct Data;
byte Buffer[34];
} Alla_Bytes_I_Samma_Klump = {en massa värden};
kan ju inte fungera för vilken del är det man anger? T_RF_Data_Struct eller Buffer?
union
{
T_RF_Data_Struct Data = {en massa värden};
byte Buffer[34];
} Alla_Bytes_I_Samma_Klump;
kan kanske fungera... om kompilern innehåller kod som kopierar över data från ROM till RAM.
Postat: 27 december 2008, 20:35:56
av stekern
I detta exempel skulle man t.om. kunna använda byte pekare som pekar på structen och sedan lägga in värdena direkt, men det är såklart snyggare med union.
Ett kodexempel för att visa vad jag menar:
Kod: Markera allt
#include <stdio.h>
typedef struct {
char test1;
char test2;
} test_t;
int main(){
test_t test;
char *ptr;
ptr = (char *)&test;
*ptr++ = 'A';
*ptr ='B';
printf("test.test1 = %c, test.test2 = %c\n",test.test1,test.test2);
return 0;
}
outputen blir:
fast nu när jag sitter och skriver det här börjar jag bli fundersam på om det är garanterat att datat ligger linjärt strukturerat i en struct?
Jag har iaf aldrig vart med om att ovanstående inte skulle fungera...
Postat: 27 december 2008, 20:44:35
av mri
Skall man skriva linjärt över en struct med 'union' eller en byte-pekare får man se till att ordna variablerna så att man vet att kompilatorn inte sätter in "padding" för att "aligna" variabler, eller så får man se till att strukturen är "packed". Finns icke-standard attribut för att göra detta.
Postat: 27 december 2008, 20:59:04
av stekern
Aha, har man lärt sig nåt nyttigt idag med
Postat: 27 december 2008, 23:05:35
av speakman
Sedan C99 finns
Tagged Initializing Format också:
Kod: Markera allt
T_RF_Data_Struct Data = {
.SenderID = 0x01,
.ReciverID = 0x02,
};
Postat: 27 december 2008, 23:19:05
av kimmen
Såg just att jag såg fel:
Kod: Markera allt
union
{
T_RF_Data_Struct Data;
byte Buffer[34];
} Alla_Bytes_I_Samma_Klump; // Kan jag här sätta SenderID till ett värde??
Är ju en variabeldefinition så ja det går. Det är ju inget problem att pilla på "Alla_Bytes_I_Samma_Klump.Data.SenderID" i en ny sats. Med tanke på att det är en array så kommer man behöva mer än bara en tilldelning. En variant är att som tidigare sätta hela Alla_Bytes_I_Samma_Klump.Data = förinitialiserad_T_RF_Data_Struct-en;
Postat: 27 december 2008, 23:21:38
av kimmen
stekern skrev:
fast nu när jag sitter och skriver det här börjar jag bli fundersam på om det är garanterat att datat ligger linjärt strukturerat i en struct?
Jag har iaf aldrig vart med om att ovanstående inte skulle fungera...
De ska nog ligga i ordning i alla fall, annat har jag inte varit med om, men däremot kan det bli hål mellan fälten för att en 4-bytes variabel ska börja på en adress jämnt delbart med 4 osv. Är det bara fält med char-storlek så brukar inte hända något konstigt.
Postat: 28 december 2008, 09:37:42
av stekern
Jo, det var ju just det som mris inlägg beskrev
Postat: 28 december 2008, 18:18:31
av kimmen
Ja. (Inläggen kommer ju inte upp om man inte uppdaterar sidan...)
Postat: 1 januari 2009, 21:53:13
av thepirateboy
Tackar för svar. Lyckades aldrig tilldela initvärden till unionen men jag skippar den och kör med en bytepekare istället, det går lika bra. Att tilldela värden till structen verkar inte vara nåt problem när man väl fattade syntaxen.
Nedanstående kod fungerar bra med avr-gcc kompilatorn:
Kod: Markera allt
typedef struct
{
unsigned char start_TX;
unsigned char counter[3];
unsigned char sep_sign_1;
unsigned char serial[2];
unsigned char sep_sign_2;
unsigned char ad_value[3];
unsigned char sep_sign_3;
unsigned char temperature[5];
unsigned char sep_sign_4;
unsigned char batt_volt[4];
unsigned char stop_TX;
}T_TX_data_struct;
T_TX_data_struct tx_data = {STX,"000",';',"00",';',"000",';'," 00,0",';',"0,00",ETX};
unsigned char *ptr_tx_data = (unsigned char *)&tx_data;
nrf24l01_write_tx_payload(ptr_tx_data, RF_PAYLOAD, true); // Transmit 23 bytes
Postat: 2 januari 2009, 00:02:30
av speakman
Funkar inte Tagged Initializing Format för unions heller?