Användning av struct
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.
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.
Senast redigerad av kimmen 27 december 2008, 17:30:47, redigerad totalt 1 gång.
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...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.
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.
-
- EF Sponsor
- Inlägg: 2109
- Blev medlem: 27 augusti 2005, 20:57:58
- Ort: Borlänge
Jag tänkte snarare om det gick i samband med deklarationen av Unionen i detta exempel:
Testvar = Default verkar annars fungera med avr-gcc, kompilatorn klagar iaf inte på tilldelningen.
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.
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.
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.
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:
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...
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;
}
Kod: Markera allt
test.test1 = A, test.test2 = B
Jag har iaf aldrig vart med om att ovanstående inte skulle fungera...
Sedan C99 finns Tagged Initializing Format också:
Kod: Markera allt
T_RF_Data_Struct Data = {
.SenderID = 0x01,
.ReciverID = 0x02,
};
Såg just att jag såg fel:
Ä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;
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??
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.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...
-
- EF Sponsor
- Inlägg: 2109
- Blev medlem: 27 augusti 2005, 20:57:58
- Ort: Borlänge
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:
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