C fråga

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
mrhedin
Inlägg: 114
Blev medlem: 3 maj 2005, 19:46:24
Ort: Trollhättan/Kiruna
Kontakt:

C fråga

Inlägg av mrhedin »

Tja!

Det här är säkert dunderlätt för nån som kan.
Om jag har följande:

Kod: Markera allt

unsigned int funktion(void)
{
   if(a == 1)
   {
      return 0;
   }
return 1;
}
Om a är 1 bryter den då funktionen direkt när nollan returnerats, eller fortsätter den neråt i funktionen så ettan returneras?
Användarvisningsbild
Icecap
Inlägg: 26648
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Första 'return()' som påträffas returnerar med resultatet, alltså kommer 'funktion()' att "svara tillbaka" med 0 om 'a' är 1.
Användarvisningsbild
baron3d
EF Sponsor
Inlägg: 1353
Blev medlem: 1 oktober 2005, 23:58:43
Ort: Torestorp

Inlägg av baron3d »

Funktionen avslutas med return.
Är a=1 returneras 0.
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

mrhedin: Varför inte prova och se?
mrhedin
Inlägg: 114
Blev medlem: 3 maj 2005, 19:46:24
Ort: Trollhättan/Kiruna
Kontakt:

Inlägg av mrhedin »

Cykze: Enklare å fråga =)

Tackar så mycket!
Användarvisningsbild
ahlsten
Inlägg: 659
Blev medlem: 12 november 2005, 00:24:14
Ort: Uppsala

Inlägg av ahlsten »

Vore det inte bättre att skriva en if-sats som enbart innehåller en förändring av returvärdet och enbart ha en return i slutet av funktionen?
ex:

Kod: Markera allt

int foo(int a){
	int returnValue = 1;
	if(1 == a){
		returnValue = 0;
		//do stuff
	}
	return(returnValue);
}
Funktionen kan bli så faslig att underhålla annars.
Man råka på problem om man enligt samma tankesätt utelämnar en return som inte är villkorlig, dvs i vissa fall returnerar funktionen inget alls! Man får aldrig glömma att C är lömskt :wink:
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Nja, jag anser nog att "return" tidigt i funktioner är en fördel.
Annars får man hela tiden ta hänsyn till tidigare kriterier.
Ju tidigare man kan konstatera att en funktion t.ex. inte kan fortsätta p.g.a. någon kriterie, ju lättare är det att göra en snygg, logisk och funktionsfull funktion.
Att ta med ett returvärde genom hela funktionen låter väldigt rörigt...

Mvh
speakman
Användarvisningsbild
Icecap
Inlägg: 26648
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Sen finns det ju anledning till att man kan avsluta funktionen tidigare: det är mindre kod som ska löpas igenom vilket ger snabbare program.

Om man har problem att underhålla sina rutiner har man definierad dom dåligt till att börja med.

När jag gör program börjar jag alltid med att definiera vilka rutiner jag behöver och vad de förväntar som input och vad de ger i output. Kan jag inte göra den definition vet jag att det kommer att bli problem.

Jag definierar även värden som är gemensamma för mer än 1 rutin och/eller som kan komma att ändras under projektets gång, det kan vara array-storleker, min/max värden osv.

På mitt projekt med Janfires pelletsbrännare har jag en hel fil enbart med "konstant" definitioner, en annan fil med alla texter och i huvudfilen är det 14 olika parametra som väljer om det är labb-program eller produktionsprogram.

Skulle jag göra mina rutiner så att de "släpade" med ett returvärde kommer det ju inte att fungera, vara sig i logik som i hastighet.

Vad jag däremot ofta använder är #define, om man har ett värde som ska vara tydligt men består av en hårdvara-hänvisning kan det vara mycket lättare att läsa med define. Ett exempel från ett MikroC-program:

PORTA.F1 = true; // Turn on green LED
PORTA.F2 = false; // Turn off red LED

Utan kommentarer är det skit att läsa, alltså MÅSTE man kommentera varenda gång man fibblar med dessa LED. Gör man däremot såhär:
#define LED_GREEN PORTA.F1
#define LED_RED PORTA.F2
kommer
LED_GREEN = true;
LED_RED = false;
nära nog att kommentera sig själv fastän att det efter preprocessorn kommer att vara identisk för kompilern.

Om jag gör en funktion som ska returnera ett värde är det första jag lägger in i den rutin en return(); med ett default värde eller ett värde jag enkelt kan leta upp till var det kommer ifrån, ska det svaras med 0-100 t.ex. kommer default värdet att vara -1.
Användarvisningsbild
ahlsten
Inlägg: 659
Blev medlem: 12 november 2005, 00:24:14
Ort: Uppsala

Inlägg av ahlsten »

Nu handlar det ju förvisso om embedded-produkter och har man en rutin som ofta anropas kanske man tom ska skriva den i ASM, men generellt spelar nog inte en breq, cpse eller dylikt extra så stor roll?
Kod som är villkorlig är villkorlig :wink:

Visst är det viktigt att abstrahera och så fort man är klar med det översätter man det i headerfiler, implementera funktioner är nog det sista som händer... men jag tycker (jovisst det är min helt personliga åsikt) nog fortfarande att det kan vara bra att undvika fantomreturer och andra pitfalls då det är så jobbigt att debugga i dessa fall. För det är ju inte i abstraktionen som det slår slint i sådana här fall utan i implementationen, när man försöker optimera/utveckla sin funktion (eller nån annans för den delen).
För mig handlar det ju inte om att skriva en funktion som fungerar som man tänkt sig, det handlar om att skriva en funktion som fungerar även om det inte går som man tänkt sig...
Användarvisningsbild
Icecap
Inlägg: 26648
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Jovars, jag kan förstå ditt synsätt.

Nu har jag aldrig upplevd "fantomreturer" vad det nu är och jag brukar lägga krutet på att rutinen fungerar i alla lägen, om man uppnår "även om det inte går som man tänkt sig..." och har gjort kod som fallera av den anledning bör man tänka om sitt programmeringssätt...
Användarvisningsbild
ahlsten
Inlägg: 659
Blev medlem: 12 november 2005, 00:24:14
Ort: Uppsala

Inlägg av ahlsten »

"även om det inte går som man tänkt sig" handlar självfallet om yttre omständigheter, t.ex. att temp-sensorn går sönder i pelletsbrännaren och ger en rökgastemperatur på -1 grader C. Fantomretur skulle då tex kunna vara:

Kod: Markera allt

int feedPellets(int temp){
	if(temp > 350){
		return(0);
	}
	elseif(temp > 100)
		return(32);
	}
}

Och nu förstår jag att ingen medvetet skulle skriva såhär, men det är ett typexempel på en fantomretur. :)
Användarvisningsbild
Icecap
Inlägg: 26648
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Jahaaa.. OK, jag hajar.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Angående multipla return from en funktion, så brukar jag personligen,
när det gäller assembler, anse att man enbart ska ha en RETURN i varje
subrutin. Det blir betydligt snyggare, och det är mindre risk att man av
misstag lägger dit något nytt som skall utföras direkt före den sista
RETURN'en, och missar den högre upp i koden. "Priset" är en extra GOTO
ner till den avslutande RETURN...
Användarvisningsbild
Icecap
Inlägg: 26648
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Jag är är inte helt inne på samma linje, jag anser att man kan trycka in en 'return' om det är befogad, jag delar i stället upp med kommentarer för att säkerställa att man inte gör klantigheter. Dock är det ofta sådan att jag läggar in returerna under optimeringsfasen, under FSAF-fasen ("Få-Skiten-Att-Fungera") håller jag oftast ihop rutinerna så mycket som möjligt.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

OK, vi kanske ser lite olika på det.

Jag tycker att, om man ligger så "on the edge" så att man måste skriva kod som
riskerar att bli svår att underhålla i framtiden, så har man större problem... :-)
Skriv svar