Fråga: #define i C, kombinera värden
Fråga: #define i C, kombinera värden
Problem:
Ibland (väldigt ofta) definierar jag hårdvara-pinnar med ett namn och deras port-pinne, detta för att göra skrivning & läsning av programmen enklare. Ett exempel:
#define LED_Red PDR5_P55
#define LED_Green PDR5_P56
"#define" gör ju en rent textmässig utbyte så när jag skriver "LED_Green = false; " blir det ju av kompilerns preprocessor gjort om till "PDR5_P56 = false;".
Så långt allt bra, det är ju verkligt en användbar funktion för läsbarhetens skull.
Men jag skulle vilja gå ett steg längre...
Jag har inte hittat något som skulle göra det men jag skulle vilja att man t.ex. kunde skriva såhär:
Först definierar jag alla hårdvaraanslutningar i t.ex. ett kontaktdon:
....
#define Pin_18 PDR8_P86
#define Pin_18_D DDR8_D86
....
Finns eg. 26 pinnar i detta projekt men jag vill inte tråka ut er.
Sedan definierar jag vad jag använder:
#define Some_Signal Pin_18
Och här kommer grejen: Jag skulle gärna vilja ha ett sätt att automatisk kunde lägga till någon text i förlängning av en #define text. I exemplet ovan skulle jag gärna vilja lägga till:
"Some_Signal" + "_D" vilket i slutändan funktionellt skulle bli till en: #define Some_Signal_D
Detta skulle göra det enkelt att göra enkla och stabila hårdvarumässiga definitioner som enkelt kan flyttas och där skrivfel minskas markant.
Men ta mig tusan om jag har hittat hur man ska göra... så är det någon som kan ge mig tips om hur man gör? Om det nu ens går att göra alls...
Ibland (väldigt ofta) definierar jag hårdvara-pinnar med ett namn och deras port-pinne, detta för att göra skrivning & läsning av programmen enklare. Ett exempel:
#define LED_Red PDR5_P55
#define LED_Green PDR5_P56
"#define" gör ju en rent textmässig utbyte så när jag skriver "LED_Green = false; " blir det ju av kompilerns preprocessor gjort om till "PDR5_P56 = false;".
Så långt allt bra, det är ju verkligt en användbar funktion för läsbarhetens skull.
Men jag skulle vilja gå ett steg längre...
Jag har inte hittat något som skulle göra det men jag skulle vilja att man t.ex. kunde skriva såhär:
Först definierar jag alla hårdvaraanslutningar i t.ex. ett kontaktdon:
....
#define Pin_18 PDR8_P86
#define Pin_18_D DDR8_D86
....
Finns eg. 26 pinnar i detta projekt men jag vill inte tråka ut er.
Sedan definierar jag vad jag använder:
#define Some_Signal Pin_18
Och här kommer grejen: Jag skulle gärna vilja ha ett sätt att automatisk kunde lägga till någon text i förlängning av en #define text. I exemplet ovan skulle jag gärna vilja lägga till:
"Some_Signal" + "_D" vilket i slutändan funktionellt skulle bli till en: #define Some_Signal_D
Detta skulle göra det enkelt att göra enkla och stabila hårdvarumässiga definitioner som enkelt kan flyttas och där skrivfel minskas markant.
Men ta mig tusan om jag har hittat hur man ska göra... så är det någon som kan ge mig tips om hur man gör? Om det nu ens går att göra alls...
Re: Fråga: #define i C, kombinera värden
Nu har jag inte tänkt riktigt, men ett macro som utnyttjar concatenation borde kanske gå
att få till snyggt? ett exempel:
http://gcc.gnu.org/onlinedocs/gcc-3.2/c ... ation.html
Det är ##:arna som är magiken, de klistrar ihop argumenten.
MVH: Mikael
att få till snyggt? ett exempel:
http://gcc.gnu.org/onlinedocs/gcc-3.2/c ... ation.html
Det är ##:arna som är magiken, de klistrar ihop argumenten.
MVH: Mikael
Re: Fråga: #define i C, kombinera värden
Det låter som du skulle vilja ha två "nivåer" av preprocessormakron..det gär nog inte utan att bygga en egen preprocessor som tuggar igenom filen innan kompilatorns preprocessor kickar in...
I just fallet med D ovan verkar det vara för att annda en annan pinkonfig vid Debug. Då skulle du istället kunna använfa #ifdef/#else/#endif
#ifdef Debug
#define Some_Pin Pin18D
#else
#define Some_Pin Pin18
#endif
/johan
I just fallet med D ovan verkar det vara för att annda en annan pinkonfig vid Debug. Då skulle du istället kunna använfa #ifdef/#else/#endif
#ifdef Debug
#define Some_Pin Pin18D
#else
#define Some_Pin Pin18
#endif
/johan
Re: Fråga: #define i C, kombinera värden
adent: Bra! Men tyvärr inte helt i mål..
johano: jepp, det är tydligen just problemet: preprocessorn kör bara ett varv...
Själva sammanfogningen går bra men kompilern gnäller ändå över att 'Some_Signal_D' är odefinierat. Det är inte det men det behövs ytterligare ett varv i preprocessorn för att få det hela att fungera och det ids jag inte lägga energi på.
Och det är inte en fråga om att få endera av Some_Signal eller Some_Signal_D, det är frågan om att skapa Some_Signal_D utifrån Some_Signal's verkliga innehåll. Suffixen _D (eller_Dir) använder jag för att ange riktningsregistret till en port.
Tänk såhär:
* Jag anger att LED_Green finns på en viss pinne i ett kontaktdon, t.ex. Pin_18. Jag har tidigare definierat denna som PDR5_P55. Jag har även definierat Pin_18_D som DDR5_D55, alltså riktningsregistret för den pinne.
Jag önskar alltså att jag kunde definiera LED_Green till Pin_18 varefter det fanns lite "automatiska" #defines som ville ta LED_Green och lägga till _D till <innehållet> i LED_Green (Alltså "Pin_18") och lägga till _D så att slutresultatet ville bli samma som att skriva:
#define LED_Green_D Pin_18_D
Nåväl, i.o.m. att preprocessorn bara kör ett varv är det rimligt dödfött... men jag tacka ändå för hjälpen. Det är ju ändå ett lyxproblem så jag kan nog leva utan denna funktion.
johano: jepp, det är tydligen just problemet: preprocessorn kör bara ett varv...
Själva sammanfogningen går bra men kompilern gnäller ändå över att 'Some_Signal_D' är odefinierat. Det är inte det men det behövs ytterligare ett varv i preprocessorn för att få det hela att fungera och det ids jag inte lägga energi på.
Och det är inte en fråga om att få endera av Some_Signal eller Some_Signal_D, det är frågan om att skapa Some_Signal_D utifrån Some_Signal's verkliga innehåll. Suffixen _D (eller_Dir) använder jag för att ange riktningsregistret till en port.
Tänk såhär:
* Jag anger att LED_Green finns på en viss pinne i ett kontaktdon, t.ex. Pin_18. Jag har tidigare definierat denna som PDR5_P55. Jag har även definierat Pin_18_D som DDR5_D55, alltså riktningsregistret för den pinne.
Jag önskar alltså att jag kunde definiera LED_Green till Pin_18 varefter det fanns lite "automatiska" #defines som ville ta LED_Green och lägga till _D till <innehållet> i LED_Green (Alltså "Pin_18") och lägga till _D så att slutresultatet ville bli samma som att skriva:
#define LED_Green_D Pin_18_D
Nåväl, i.o.m. att preprocessorn bara kör ett varv är det rimligt dödfött... men jag tacka ändå för hjälpen. Det är ju ändå ett lyxproblem så jag kan nog leva utan denna funktion.
Re: Fråga: #define i C, kombinera värden
Jag vet inte om jag uppfattat behovet korrekt, men är det ungefär detta :
Kod: Markera allt
$
$
$ type test.c
#include <stdio>
#define LED_Green "Pin_18"
#define LED_Green_D LED_Green ## "_D"
void main()
{
char *text[20];
text[19] = "\0";
printf("LED_Green = ");
*text = LED_Green;
printf(*text);
printf("\n");
printf("LED_Green_D = ");
*text = LED_Green_D;
printf(*text);
printf("\n");
}
$ cc test
$ link test
$ run test
LED_Green = Pin_18
LED_Green_D = Pin_18_D
$
Re: Fråga: #define i C, kombinera värden
Rätt - men ändå fel...
Jag behöver inte texten, jag behöver att stycka ihop beteckningar inför preprocessorn.
Jag vill alltså ha det så att:
#define LED_Green Pin_18
medelst lite magi även utlöser:
#define LED_Green_D Pin_18_D
Dessa exempel är ju simpla och banala men i en del andra sammanhang kan det bli oerhört värdefullt att ha sådan en funktion som kan utföra en del automatiska funktioner som säkerställer korrekt definitioner.
Jag behöver inte texten, jag behöver att stycka ihop beteckningar inför preprocessorn.
Jag vill alltså ha det så att:
#define LED_Green Pin_18
medelst lite magi även utlöser:
#define LED_Green_D Pin_18_D
Dessa exempel är ju simpla och banala men i en del andra sammanhang kan det bli oerhört värdefullt att ha sådan en funktion som kan utföra en del automatiska funktioner som säkerställer korrekt definitioner.
Re: Fråga: #define i C, kombinera värden
OK.
Problemet är att jag inte förstår vad du menar med "automatiskt" och "magi"...
Kan du ge ett kort exempel på hur du skulle vilja skriva koden.
> medelst lite magi även utlöser:
> #define LED_Green_D Pin_18_D
Du menar att du inte ens ska behöva SKRIVA den raden alls !?
Den ska bara finnas där endå ?
Problemet är att jag inte förstår vad du menar med "automatiskt" och "magi"...

Kan du ge ett kort exempel på hur du skulle vilja skriva koden.
> medelst lite magi även utlöser:
> #define LED_Green_D Pin_18_D
Du menar att du inte ens ska behöva SKRIVA den raden alls !?
Den ska bara finnas där endå ?
Re: Fråga: #define i C, kombinera värden
Icecap, läste du verkligen exemplet ordentligt?
Efter koden
Så kommer LED_Green att vara "Pin_18" och LED_Green_D att vara "Pin_18_D".
Om du nu ska ändra till Pin 17 behöver du bara ändra den första #define, inte den andra.
Efter koden
Kod: Markera allt
#define LED_Green "Pin_18"
#define LED_Green_D LED_Green ## "_D"
Om du nu ska ändra till Pin 17 behöver du bara ändra den första #define, inte den andra.
Re: Fråga: #define i C, kombinera värden
Jo, jag vet om detta och det fungerar - fast inte på det vis jag vill ha.
Sodjan: just så, jag vill ange t.ex. 'Pin_18' varefter någon annan #define lägger till fler #define med t.ex. 'Pin_18_D' osv. Jag bekymrar mig bara om en här, kan man göra en, kan man göra fler.
Problemet är att preprocessorn inte kör varv nog, den kommer till slutresultatet men ett steg för sent så att säga.
Om vi antar att jag i en hårdvara definitionsfil har skrivit:
#define Pin_18 PDR5_P54 /* Betyder portregister 4 i port 5 */
#define Pin_18_D DDR5_D54 /* Betyder riktningsregister bit 4 för port 5 */
då kommer preprocessorn att ersätta alla förekomster av "Pin_18" med "PDR5_P54" (rent textmässigt) liksom alla förekomster av "Pin_18_D" blir ersatt av "DDR5_D54".
Om jag sedan skriver:
#define LED_Green Pin_18
kommer preprocessorn att byta alla förekomster av "LED_Green" med (i slutändan) "PDR5_P54".
Det jag söker är att jag kan lägga in några "magiska rader" som lägger till en valfri ändelse, t.ex:
#define LED_Green_Dir LED_Green ## _D
Denna rad GER faktisk resultatet "LED_Green_D" men jag vill att den ska ge "Pin_18_D", alltså använda "innehållet" i LED_Green (="Pin_18") som bas vilket i sin tur ersätts med DDR5_D54. Preprocessorn går alltså inte varv nog till att klara detta helt enkelt.
Allt är ett försök på att undvika dessa skrivningsfel som är ganska vanliga men ack så svåra att hitta, kan man alltså ange ett värde ett ställe och bygga andra värden beroende på detta kan man undvika många problem.
Och ja, just i detta extremt enkla exempel kan jag ju bara skriva:
#define LED_Green Pin_18
#define LED_Green_D Pin_18_D
men det är ju lite mer knepigt när man kommer upp och har ett 80-tal anslutningar, där kan det ju lätt bli fel. Kunde man istället ha en skrivning som skapar de rätta definitioner från "basen" ville många problem vara undvikna.
Sodjan: just så, jag vill ange t.ex. 'Pin_18' varefter någon annan #define lägger till fler #define med t.ex. 'Pin_18_D' osv. Jag bekymrar mig bara om en här, kan man göra en, kan man göra fler.
Problemet är att preprocessorn inte kör varv nog, den kommer till slutresultatet men ett steg för sent så att säga.
Om vi antar att jag i en hårdvara definitionsfil har skrivit:
#define Pin_18 PDR5_P54 /* Betyder portregister 4 i port 5 */
#define Pin_18_D DDR5_D54 /* Betyder riktningsregister bit 4 för port 5 */
då kommer preprocessorn att ersätta alla förekomster av "Pin_18" med "PDR5_P54" (rent textmässigt) liksom alla förekomster av "Pin_18_D" blir ersatt av "DDR5_D54".
Om jag sedan skriver:
#define LED_Green Pin_18
kommer preprocessorn att byta alla förekomster av "LED_Green" med (i slutändan) "PDR5_P54".
Det jag söker är att jag kan lägga in några "magiska rader" som lägger till en valfri ändelse, t.ex:
#define LED_Green_Dir LED_Green ## _D
Denna rad GER faktisk resultatet "LED_Green_D" men jag vill att den ska ge "Pin_18_D", alltså använda "innehållet" i LED_Green (="Pin_18") som bas vilket i sin tur ersätts med DDR5_D54. Preprocessorn går alltså inte varv nog till att klara detta helt enkelt.
Allt är ett försök på att undvika dessa skrivningsfel som är ganska vanliga men ack så svåra att hitta, kan man alltså ange ett värde ett ställe och bygga andra värden beroende på detta kan man undvika många problem.
Och ja, just i detta extremt enkla exempel kan jag ju bara skriva:
#define LED_Green Pin_18
#define LED_Green_D Pin_18_D
men det är ju lite mer knepigt när man kommer upp och har ett 80-tal anslutningar, där kan det ju lätt bli fel. Kunde man istället ha en skrivning som skapar de rätta definitioner från "basen" ville många problem vara undvikna.
Re: Fråga: #define i C, kombinera värden
Preprocessorn gör väl inte substitutioner inuti substitutioner? Det är väl det som är problemet, inte varven? För LED_Green är ju redan definierad när du kommer till #define LED_Green_Dir LED_Green ## _D
Re: Fråga: #define i C, kombinera värden
> #define LED_Green_Dir LED_Green ## _D
> Denna rad GER faktisk resultatet "LED_Green_D"
Så var det inte i mitt exempel (om "LED_Green" är definierad till något annat).
Jag har skrivit om koden lite :
Är det så du menar ?
> Denna rad GER faktisk resultatet "LED_Green_D"
Så var det inte i mitt exempel (om "LED_Green" är definierad till något annat).
Jag har skrivit om koden lite :
Kod: Markera allt
$
$ type pin_def.c
#define Pin_18 "PDR5_P54"
$
$ type test.c
#include <stdio>
#include "pin_def.c"
#define LED_Green Pin_18
#define LED_Green_D LED_Green ## "_D"
void main()
{
char *text[20];
text[19] = "\0";
printf("Pin_18 = ");
*text = Pin_18;
printf(*text);
printf("\n");
printf("LED_Green = ");
*text = LED_Green;
printf(*text);
printf("\n");
printf("LED_Green_D = ");
*text = LED_Green_D;
printf(*text);
printf("\n");
}
$ cc test
$ link test
$ run test
Pin_18 = PDR5_P54
LED_Green = PDR5_P54
LED_Green_D = PDR5_P54_D
$
Re: Fråga: #define i C, kombinera värden
Nerre> Preprocessorn gör väl inte substitutioner inuti substitutioner?
Menar du så som nedan ?
Eller menar du som en delmängd av en symbol? Då får i jag "undeclared symbol".
Men det fungerar med ## operatorn :
Menar du så som nedan ?
Kod: Markera allt
$
$ typ def_test.c
#include <stdio>
#define ABC "XYZ"
#define ABC2 ABC
#define ABC3 ABC2
#define ABC4 ABC3
#define ABC5 ABC4
#define ABC6 ABC5
void main()
{
char *text[20];
text[19] = "\0";
printf("ABC6 = ");
*text = ABC6;
printf(*text);
printf("\n");
}
$ cc def_test.c
$ link def_test
$ run def_test
ABC6 = XYZ
$
Men det fungerar med ## operatorn :
Kod: Markera allt
$
$ typ def_test.c
#include <stdio>
#define ABC "XYZ"
#define ABC2 ABC
#define ABC3 ABC2##"def"
void main()
{
char *text[20];
text[19] = "\0";
printf("ABC3 = ");
*text = ABC3;
printf(*text);
printf("\n");
}
$ cc def_test
$ link def_test
$ run def_test
ABC3 = XYZdef
$
Re: Fråga: #define i C, kombinera värden
Just det går inte att få till, men ett sätt som jag använt är att göra en struct. Vill man ha två lager då kan man ju göra (i headerfil):Icecap skrev:Sedan definierar jag vad jag använder:
#define Some_Signal Pin_18
Och här kommer grejen: Jag skulle gärna vilja ha ett sätt att automatisk kunde lägga till någon text i förlängning av en #define text. I exemplet ovan skulle jag gärna vilja lägga till:
"Some_Signal" + "_D" vilket i slutändan funktionellt skulle bli till en: #define Some_Signal_D
Kod: Markera allt
typedef struct
{
GPIO_TypeDef * port;
int position;
} PortInfo;
static const PortInfo PIN18 = { GPIOD, 5 };
#define THE_IMPORTANT_LED PIN18
static inline void setPin(PortInfo pin)
{ // STM32 bit set register
pin.port->BSRR = 1UL << pin.position;
}
static inline void resetPin(PortInfo pin)
{ // STM32 bit reset register
pin.port->BRR = 1UL << pin.position;
}
En annan möjlighet (som jag först använde) var att deklarera separata static const-variabler med olika namn inifrån ett makro med hjälp av token-pasting-operatorn ##, men det var betydligt fulare och oflexiblare.
Re: Fråga: #define i C, kombinera värden
Det är inte tillåtet att göra så här:
Då gnäller kompilatorn på "'TEST1TEST2' : undeclared identifier".
Däremot är det här OK:Programmet skriver då ut:
foobar
Kod: Markera allt
#include <stdio.h>
#define TEST1 "foo"
#define TEST2 "bar"
#define TEST3 TEST1 ## TEST2
void main() {
char *text[20];
*text = TEST3;
printf("TEST3 = %s\n", *text);
}
Däremot är det här OK:
Kod: Markera allt
#include <stdio.h>
#define TEST1 "foo"
#define TEST2 "bar"
#define TEST3 TEST1 ## "" ## TEST2
void main() {
char *text[20];
*text = TEST3;
printf("TEST3 = %s\n", *text);
}
foobar
Re: Fråga: #define i C, kombinera värden
Ni verkar väldigt intresserade i att det ska vara textbaserat men PDR5_P54 är en definierat bit i ett definierat register varför jag är otroligt likgiltig i vad som skrivs ut som text, det är en sträng som preprocessorn ska fatta, inget annat.
Jag har insett att det inte går men jag ska kolla lite imorgon, jag har en antydan av en idé jag ska testa då. Jag återkommer med resultatet.
Jag har insett att det inte går men jag ska kolla lite imorgon, jag har en antydan av en idé jag ska testa då. Jag återkommer med resultatet.