Användning av struct

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Inlägg 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.
Senast redigerad av kimmen 27 december 2008, 17:30:47, redigerad totalt 1 gång.
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Inlägg 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.
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg 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.
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Inlägg 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.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg 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.
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Inlägg 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:

Kod: Markera allt

test.test1 = A, test.test2 = B
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...
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Inlägg 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.
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Inlägg av stekern »

Aha, har man lärt sig nåt nyttigt idag med
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Sedan C99 finns Tagged Initializing Format också:

Kod: Markera allt

T_RF_Data_Struct Data = {
    .SenderID = 0x01,
    .ReciverID = 0x02,
};
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Inlägg 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;
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Inlägg 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.
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Inlägg av stekern »

Jo, det var ju just det som mris inlägg beskrev
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Inlägg av kimmen »

Ja. (Inläggen kommer ju inte upp om man inte uppdaterar sidan...)
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg 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 
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Funkar inte Tagged Initializing Format för unions heller?
Skriv svar