Välkommen till linuxportalen.se!

Linuxportalen.se är Sveriges största och aktivaste webbplats för användare av öppen- och fri programvara.

Du besöker Linuxportalen.se som gäst vilket begränsar din möjlighet att använda webbplatsens alla funktioner. Genom att registera dig som medlem får du inte bara möjlighet att söka bland webbplatsens innehåll, skapa nya och delta i befintliga diskussioner, skapa din egen blogg, kommunicera med andra medlemmar genom privata meddelanden och delta i omröstningar. Du får också tillgång till Veckans Kadavro - en seriestrip unikt skapad för Linuxportalen.se!

Registeringen sker snabbt och är helt kostnadsfri - tveka inte, bli medlem idag!

Kristian: Programmera objektorienterat i C

C är som bekant ett procedurorienterat språk, i motsats till de flesta av dagens (objektorienterade) sådana. Även om språket inte formellt stödjer objektorienterade tekniker går de att implementera i C. Särskilt enkelt är det ifall arv är inte nödvändigt och man egentligen bara vill abstrahera en typ, då klarar man sig med en strukturpekare och ett gäng funktioner. Tillåts arv av en enda gemensam bastyp kommer man undan med en pekare till en tabell av virtuella funktioner.

Desto svårare blir det om man vill åstadkomma arv på godtyckliga bastyper i flera nivåer. GTK+ är skrivet i C och använder ett system som stödjer detta - GObject. GObjekts stödjer också hantering av signaler och en mängd andra tekniker. Dessvärre är de mycket tidsödandet att skriva och underhålla. En simpel klass med två "get/set"-metoder kan uppta 2-3 sidor med kod, vilket är anledningen till att mycket av utvecklingen av GTK+-program sker i python, C++ eller C#.

Det finns emellertid ett verktyg som gör livet så mycket lättare för oss som gillar C. Det heter "GObject builder" - gob. Genom detta verktyg kan man skapa klasser på bara några rader, där metoderna skrivs med en syntax som är snarlik Java. Klasserna sparas i filer med ändelsen .gob och körs genom preprocessorn gob. Den genererade .c -filen tas med bland projektet källkodsfiler och en av headerfilerna inkluderas i de .c-filer som använder klassen.

Alla som gillar C, Objective C och Java mer än C++ ska ta en kik här. Jag har länge dragit mig för att koda GTK+ i C, men nu är det en barnlek Smile

Alternativ för kommentarvisning

Välj ditt önskade sätt att visa kommentarerna och klicka på "Spara" för att verkställa dina ändringar.

trappskis bild

Fränt. Själv är jag en lat programmerar så jag kodar mest i C# nuförtiden Wink
Lite objektorienterad C har jag allt lekt med. Men inte i större mängder.

______________________________________________________________
(X.x )
(/¯¯\) (")_(") Kill the damn bunny before it's too late!

Kristians bild

Om 10 år tror jag inte att någon programmerar i C/C++ ifall de verkligen inte behöver. Utveckling i språk som Java/C# är betydligt billigare i utvecklingstid och debuggtid, vilket är det enda som kommer spela roll när datorer blir snabbare och får mer och mer minne.

Jag kan dock mycket väl ha fel. Vad gäller C kan jag dock bara citera Mark Twain "”Ryktet om min död är kraftigt överdrivet...”

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

Kristians bild

Jag borde verkligen plugga.......

Testade att skriva ett program som skapar 100000 GObjects (innehållandes en variabel och två metoder utöver de som finns i GObject), anropar en metod och frigör alla objekt. Jag skrev också en version i C++ med en klass med motsvarande funktionalitet, där 100000 objekt skapas med new, anropar en virtuell metod och frigörs med delete.

C-versionen körs på 0.230 sek, medan C++-versionen körs på 0.070 sekunder. GObject-versionen är i detta fall tre gånger långsammare. C-versionen måste anropa kod i ett dynamiskt laddbart bibliotek och göra typcheckar vid varje anrop. Dessutom har varje objekt i C-versionen bärlast ifrån basklassen GObject. Objekt i C++ ärver inte nödvändigtvis ifrån en gemensam basklass. g++ optimerar säkerligen bättre än vad som är möjligt för för gcc vid användning av GObject, då dessa inte är inbyggda i språket.

*edit*
Skrev samma program i C# och Java
Resultatet blev 0.100 sekunder för C# (Mono) och 0.120 sekunder för Java-versionen.

Nu ska man inte använda new/delete i onödan när man kodar C++. Istället ska man använda stacken när så är möjligt, eftersom new/delete är kostsamma anrop. Om jag skriver om programmet i god C++-stil så att de 100000 objekten läggs på stacken tar exekveringen 0.010 sekunder att utföra Laughing out loud (jag kontrollerade i assemblerkoden att g++ inte totalt optimerat bort programmet)

25 gånger snabbare än GObject-versionen Wink

Slutsats?

---------------------------------
where my .emacs is, that's my home

---------------------------------------

 

Kristians bild

Jag har börjat skriva en liten testapplikation i GTK+ (i C) med hjälp av GObject Builder. Riktigt nice

Koden är på 218 rader, snyggt avdelat i subklasser för fönstret, "windows" och toolbaren Smile Det är nästan som att koda i python eller java

Den genererade koden ligger på 956 rader, dvs 738 rader extra som jag slapp skriva. Visserligen så gör programmet ingenting Wink Det ser bara fint ut

source

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

Kristians bild

Ja C# (och Java) är nice Smile Jag ser dock inte fram emot den dag då alla program i systemet körs i var sin virtuell maskin. Även om program skrivna i Java/C# numera inte alls behöver vara långsammare än motsvarade i C/C++ så upptar de betydligt mycket mer minne.

Jag provade precis att skriva två testprogram

import java.io.*;

public class JavaTest {
        public static void main(String [] args) throws IOException {
                System.in.read();
        }
}
#include stdio.h

int main() {
        getchar();
        return 0;
}

Båda startas och får stå och tugga. Varje instans av java-versionen upptar 3.6 MB medan varje instans av c-versionen klarar sig med 56 KB. Som en jämförelse upptar en instans av GEdit (skrivet i C och använder GTK+) 4.0 MB.

Visserligen kommer dagens maskiner med 1-2 GB RAM och om det inte räcker finns swap, men jag tycker ändå att det är slöseri med minne.

Förmodligen resonerade man likadant på 70-talet när programmerare gick ifrån assembler -> c Wink

GTK+/Gnome är ruskigt tunggrott så minnesjämförelsen har säkerligen mindre betydelse när vi börjar ladda in dessa och andra bibliotek.

*edit*
Ett likadant "avklätt" C#-program i Mono tar 2.0 MB

------------------------------
where my .emacs is, that's my home

---------------------------------------

 

mikaeljs bild

På vilket sätt är C# användbart för en *nix användare? Läste snabbt om C# på wikipedia och introtexten får ju en att tro att det är ett windowsspecifikt språk.

mikaeljs bild

Det finns väl fler språk som kommer klara av framtiden med, och inte bara java/c#? Även om inte c/c++ kanske kommer vara så intressant om 10 år så borde ju flera andra språk kunna erbjuda liknande. Eller har jag fel?

Personligen hoppas jag verkligen att java och c# inte blir dominerande bland applikationer. Jag ser hellre att applikationer i språk som python, perl, ruby osv växer och blir ett ännu bättre alternativ än vad det är idag. Smile

dholms bild

Prova att sätta volatile framför deklarationen så skrämmer du bort GCCs optimerare. Smile
Jag är inte helt hundra på att ett objekt kan vara volatile men det borde gå.

--
Don’t take life too seriously, you won’t get out alive.

norbergs bild

Jag tror du har helt rätt i att användandet av C/C++ kommer att ha minskat (tyvärr) om 10 år när det gäller datorer. Men att det kommer kompenseras till viss del av inbyggda system där ström och resurser är mycket mer begränsade, som ett exempel kan jag ta mitt intresse för programmering av microprocessorer dessa små 8 bitars IC kretsar med kanske bara 128 byte ram och 2KB programutrymme låter inte sig programmeras i mycket annat än assembler och C. Själv har jag gått från högnivåspråk mot mer maskinnära (Basic -> Python -> PHP -> C -> C++). Jag deltog i Programmeringsolympiaden nu i vår vilket är en programmerings tävling för gymnasie ungdomar. Jag vara en av få som skrev i det enligt många svårare språket C med kom ändå en poäng ifrån final, nu var det knappast så att det var C fel att det inte gick bättre,utan snarare att jag faktiskt aldrig tävlingsprogrammerat tidigare och kanske att de flesta andra var ett år äldre.

Jag vet att jag fortfarande kommer programmera i C och C++ om 10 år, kanske inte lika mycket, men jag kommer att göra det *frivilligt*

alberts bild

Jag skrev nyss en rutin för att mixa två ljudkanaler till en och mätte tiden för olika implementationer. Att mixa två kanaler (2 st 32kb buffrar i en loop som körs 2^15 ggr, sammanlagt 1Gb) tog ungefär 1 sekund i den rena c-versionen. I versionen med gas och inline mmx-assembler tog samma sak 0.2 sekunder. 5 ggr snabbare alltså. Sen prövade jag att göra samma sak med memcpy(). Men det visade sig att libc-versionen av memcpy() var snabbare... Det är alltid intressant att mäta tider. Om man kompilerar med -pg och sedan kör gprof så får man massor av matnyttig information.
 
Det är liksom en sport att optimera ett program, även om man hade hunnit skriva 10 program på samma tid så ger det en speciell tillfredsställelse när man skrivit ett litet, snabbt och optimalt program för att lösa en specifik uppgift. Sen kan man ju alltid köra gprof innan man börjar för att ta reda på vilka rutiner man ska optimera i sitt program.

Kristians bild

*liten uppdatering*

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

lundatoks bild

Kristians bild

Python är riktigt stort bland utvecklare av både *nix och Windows. Vad jag inte gillar är att man saknar stark typning och en del argumentkontroll. Det är inte så kul när ett program kraschar under körning för att man stavat fel på en metod. Men det kanske går att aktivera typning även i Python/Ruby? Någon som vet?

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

iveqys bild

lite inspirerad av dig körde jag just ett test gvim vs emacs. Emacs drog iofs mycket mer processortid i uppstarten men tog faktiskt mindre RAM-minne...

vim börjar bli tungt Sad

trappskis bild

Jag är helt klart av samma inställning som du. Ogillar verkligen program som äter minne i onödan.
Det tillsammans med att program ska ha så häftiga färggranna grafiska gränssnitt så man tappar bort sig i allt är något som starkt ogillas.

Jag har lyckats gjort en Konsoll-app i C# som tar upp runt ~12MB (Visserligen i Windows)
Då står det och väntar på en knapptryckning för att avslutas bara.
Den exkeverbara filen ligger på 20KB Laughing out loud Sourcen på 7KB. Bara för att ha något roligt att jämföra med Laughing out loud

ComputerWorld listade fö. C-programmering å sin sida som en utdöende merit:

6. C-programmering
Den som bara kan renodlad C-programmering är förmodligen arbetslös, enligt Computer Worlds experter.
Men de utvecklade varianterna C++ och C# lever vidare.

http://www.nyteknik.se/art/50851

Vad man ska tro om det vet jag inte.

______________________________________________________________
(X.x )
(/¯¯\) (")_(") Kill the damn bunny before it's too late!

Kristians bild

"Premature Optimization is the root of all evil." Donald Knuth

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

iaidokas bild

Med mono kan du koda C# även i den fria världen.

Jag är själv gammal C-progammerare och har nosat lite på Java. Kör C# på jobbet nu och måste säga att det är ett rätt trevligt språk. Dessutom skickar microsoft med emacs-keybindings till Visual Studio, så det går att koda utan att ropa "Arghh!" en gång per rad. Den läser iofs inte min .emacs-fil, men Ctrl-A och Ctrl-E och Ctrl-XS och sånt funkar iaf.

---
"Linux är så kallad slackware, gratis, det bara
ligger och väntar på dig ute i cyberspace."
- Geir Nielsen

Test.

mikaeljs bild

Ok, monorelaterat... helt ointressant för mig då. Jag vill ju inte ha nåt mono på mina datorer Wink

Kristians bild

Du såg kanske Davids länk till DVDStyler - ett riktigt kanonprogram. Det medger menyskapning samt import av video. Vad det inte fixar är korrekt konvertering av video till mpeg2. Jag importerade ett mpeg1-clip och det blev förjävligt resultat. Efter att ha körts igenom ffmpeg innan import blev resultatet strålande. Jag ska skicka ett mail till utvecklarna och uppmuntra dem att inkludera ffmpeg i importen.

Vad gäller en C#-bindning till GStreamer så finns ingen stabil i nuläget. Banshee använder PInvoke, dvs anropar nativa C-funktioner för att hantera GStreamer.

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

marwals bild

Medan alla drar ifrån med python, c# och ruby (ibland t.o.m. on rails) sitter jag och återupptäcker Pascal. Det var bland de första språk jag började använda för en herrans massa år sedan och återseendet är riktigt trevligt. Har också kikat lite på Lua och imponeras av dess snabbhet.

lundatoks bild

*kliver upp på skåpet och ritar ett kors i taket*

--
MöLUG
Distribuerat författarskap

Kristians bild

Hm, kan bero på att du liksom de flesta andra kör med den officiellt stabila emacs version 21.4. Den använder inte GTK+2 utan något gammalt äckligt mer X11-nära GUI-bibliotek.

Tyvärr är RMS en envis jäkel som tydligen inte vill släppa emacs 22 som stabil innan helvetet fryser till is. Rätt kompilerat kör emacs 23 med GTK+2 och XFT, vars fontrendering är mycket skönare för ögonen.

Hos mig tar emacs 23 11.5 MB medan GVim tar strax över 4 MB. "11.5 MB and constantly swapping" Wink

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

Kristians bild

Äsch! De som kodar operativsystem, drivrutiner och andra som kräver snabb prestanda kodar i C och kommer att fortsätta att koda i C. Vilket operativsystem ska JavaVM:en köra i ifall operativsystemet är skrivet i Java? Jag har inget vidare förtroende för vad idg-reportrarna kastar ur sig.

Även om inga nya program skrivs i COBOL finns det miljarder rader existerande kod i detta språk. Det är kod som fungerar, kod som skulle kosta multum att ersätta. Dock behöver den underhållas och anpassas till den nya tidens krav

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

jonasbjorks bild

Jag tror jag kan få ner "Hello World" på typ 48 bytes om jag skriver det i assembler. Vad säger det om språket? Att det är resurssnålt ja, men vänligt att skriva i? Nej. Både Java och Mono (C# t.ex.) använder sig av en "motor" (runtime environment) som måste laddas, denna laddas dock inte för varje applikation som körs utan bara en gång. Visst tar det lite mer minne (ibland ganska mycket mer) men vinsten av att skriva kod i Java eller C# är mycket högre. Det går betydligt snabbare att skriva ett program i dessa språk än i t.ex. assembler.

SLES10:     -rwxr-xr-x 1 root root 501804 Jun 16  2006 /bin/bash
Ubuntu/x86: -rwxr-xr-x 1 root root 700560 2007-04-11 01:32 /bin/bash
Ubuntu/PPC: -rwxr-xr-x 1 root root 793528 2006-04-22 00:51 /bin/bash

Är BASH i Ubuntu sämre än BASH i SUSE Linux Enterprise 10?

SLES10 $  ldd /bin/bash 
        linux-gate.so.1 =>  (0xffffe000)
        libreadline.so.5 => /lib/libreadline.so.5 (0xb7f38000)
        libhistory.so.5 => /lib/libhistory.so.5 (0xb7f31000)
        libncurses.so.5 => /lib/libncurses.so.5 (0xb7eea000)
        libdl.so.2 => /lib/libdl.so.2 (0xb7ee6000)
        libc.so.6 => /lib/libc.so.6 (0xb7dc4000)
        /lib/ld-linux.so.2 (0xb7f6f000)
Ubuntu/x86 $ ldd /bin/bash 
        linux-gate.so.1 =>  (0xffffe000)
        libncurses.so.5 => /lib/libncurses.so.5 (0xb7f45000)
        libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7f41000)
        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7dff000)
        /lib/ld-linux.so.2 (0xb7f97000)

Det verkar som om Ubuntu länkat in en del bibliotek statiskt i binären och oops den blev större.. Man skall nog inte stirra sig blint på minnesanvändning och storlek på filerna. I era jämförelser mellan vi och emacs blir det tydligt att emacs drar mer. Varför? Det kan inte vara så att emacs innehåller betydligt fler funktioner än vi? Eller ni tar vilken texteditor som helst och jämför den med en annan texteditor? Varför inte jämföra Nano med OpenOffice Writer? De kan båda användas för att skriva text. Vem kommer gå segrande ur den "striden"? Sen att Writer kan betydligt mer än Nano är ointressant, det är ju trots allt hur mycket RAM en texteditor använder som är intressant.. Peace!

--
SUSE Linux
Jonas Björk - like.no.other

--
Jag är grundare av och administratör på Linuxportalen. Kontakta mig om du har frågor, funderingar eller synpunkter kring Linuxportalen.se .

dholms bild

Hear hear!
Det största problemet med att optimera för tidigt är att man gör en kvalificerad gissning om var programmet spenderar sin tid. Gång på gång så har jag lurat mig själv och optimerat fel del.
Nu senast så optimerade jag en funktion för att läsa data från en fil. Den var skriven för att maximera läsbarheten och minimera möjlighet till mänskliga faktorn samtidigt som den på ett mycket elakt sätt körde över allt vad read-ahead heter så "givetvis måste det vara den som var ooptimal". Efter att ha spenderat ganska mycket tid på att trixa runt för att kunna nyttja läscachen utan att resultatet blev märkbart bättre så visade det sig att problemet var i den loop som använde sig av funktionen. Den var alldeles för tight och programmet sprang mycket snabbt runt i loopen som bestod av alldeles för få syscalls. Detta resulterade i att jag käkade upp hela min tidsslice varje gång den tråden fick chans att exekvera utan att låta mina andra trådar få köra. Efter att jag lät min sleep få köra lite oftare så ökade prestandan med ganska så mycket.
 
Skriver man en applikation för sig själv så är det jättekul att spendera en massa tid på att experimentera med optimeringar. Men om man utvecklar saker som är tänkt att hjälpa andra så är kvalitet bättre än att du utnyttjar oerhört liten CPU-slice. En användare blir aldrig imponerad av ett program som kraschar för att man råkat få in en liten off-by-one i sin AltiVec-kod och behövde två veckor på sig att leta upp det. Däremot om du har ett program som har dugliga svarstider på operationer och aldrig kraschar så har du också nöjda användare.
Steve McConnell har en bra tumregel som jag skall försöka paracitera. Man skall skriva sin kod för att minimera den mänskliga faktorn. Alltså så skall man satsa på läsbarhet och enkelhet framför den mest optimerade lösningen. Om din funktion går att skriva om så att den blir snabbare utan att du samtidigt försämrar läsbarheten och enkelheten i den så är det inte en optimering, då har du skrivit fel från början.
--
Don’t take life too seriously, you won’t get out alive.

alberts bild

Knuth har aldrig skrivit något 4kb intro. Han var för upptagen med sitt tex (som inte går att uttala) och att skriva sin lättlästa novellserie taocp Smile

Kristians bild

Hm, både netbeans och eclipse har "emacs-keybindings". De stödjer kill region och yank, men inte yank-pop (dvs bläddring i kill-ring). Det stör mig. Att man inte kan starta markering med CTRL+SPACE gör att man måste flytta händerna till piltangenterna ;( Den högra delen av tangentbordet skulle jag lika gärna kunna kapa av Tongue

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

iveqys bild

mycket möjligt att du har rätt. Här är testreslutaten när jag startat emacs, gvim och scite. Lite förvånande är scite riktigt dåligt. Kan tillägga att gvim varken laddar verktygsfält eller menyer...

Lite roligt är att jag hade en föreläsare som jämt körde emacs i sina exempel, det lustiga är att han alltid körde emacs i en terminal. Inte ofta jag stött på emacs användare som håller sig till terminalen. Smile

Lua är riktigt trevligt.
Jag såg förövrigt att nya loki-setup (mojosetup) kommer ha lua för att göra egna setups.

Kristians bild

Att jämföra Nano med OpenOffice är rent löjligt. Jag jämförde ett till funktionen likvärdigt program implementerat i olika språk med avseende på minne och hastighet.

Men jag förstår din poäng Jonas. På 80-talet var det assembler som var lightweight och C som var jättebloatat. Det får vi inte glömma.

C är dock långt ifrån assembler och det är ingen slump att alla moderna språk har efterapat dess syntax då den är både enkel, kraftfull och elegant. Språket har trots allt överlevt i 35 år.

Att man valde C som bas till GTK+ berodde dels på personlig preferens, dels på att g++ inte var av lika hög kvalitet som idag och sist men inte minst därför att C är väldigt lätt att anropa ifrån andra språkbindningar. I backspeglen kan det ev. ses som ett misstag, med tanke på att QT är gjort i C++ och fungerar trots det med en mängd bindnings (ev. efter lite black magic).

Vim och Emacs är idag hyfsat funktionslika, det som gör Emacs så mycket tyngre är att den är uppbyggt på ett fundamentalt annorlunda sätt. Skaparna av Vim har byggt en kompetent editor i C och därefter möjliggjort anpassning av vissa delar via scripts och variabler.

I fallet Emacs har man byggt en mycket simpel baseditor och implementerat funktioner som att flytta markören och infoga text i C. Där ovanpå har man satt en LISP-maskin med förmåga att anropa dessa "grundfunktioner", möjlighet att ladda in en massa extra funktioner och variabler samt kommunicera med användaren genom tangentbordet och musen. Användaren kommunicerar med LISP, inte med Editorn på skärmen Wink LISP-miljön styr allt mellanarbete. Detta ger en extremt kraftfull och anpassningsbar miljö, men gör givetvis att den blir mycket mer minneskrävande. Sen är frågan ifall man behöver mer än ett operativsystem när man egentligen bara vill skriva in lite text Wink

---------------------------------
where my .emacs is, that's my home

---------------------------------------

 

iveqys bild

de tre editorerna jag jämförde har samma målgrupp och marknadsför sig till samma användningsområde. Då tycker jag att det är rimligt att jämföra dem.

Att jämföra vim och emacs är extra intressan i och med att de valt så olika vägar till att göra samma uppgift (så som Kristian beskrev).

sen beror det ju på applikationen vilka parametrar som är viktiga att jämföra. Ett officepaket kanske inte har ram-användningen som största kriterium utan möjligtvis användarvänligheten iställlet. En texteditor för programmerare har helt andra parametrar som bör jämföras. RAM-användningen är en sådan enligt mig.

alberts bild

Det går faktiskt att få ner det till 45 bytes Wink

Kristians bild

Förmodligen för att fontrenderingen är bättre i en terminal om man kör äldre emacsar, eller så var han van att ssh:a utan X Smile

Vilket fält betyder vad?

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

marwals bild

gVim... vad f-n är det? Aldrig kört och har inte installerat.
Det finns väl ingen vettig människa som installerar en X-version av ett program som inte tillför något nytt och bara kostar resurser.
Jämför Emacs med Vim och inte med gVim.

Kristians bild

Ahh, intel assembler Laughing out loud Vi håller på och skriver en kompilator för ett C-liknande språk i en kurs, himla kul Smile

----------------------------------
where my .emacs is, that's my home

---------------------------------------

 

Ja gvim är något jag bara testat en gång.
Nä vim är bäst i en konsol.

iveqys bild

oj lessen det glömde jag. Det är htop jag använt så fälten betyder.

user, pri, ni, virt, res, shr, s, cpu%, mem%, time+, command

iveqys bild

gvim är den grafiska versionen av vim. Det är inget som behöver installeras seperat utan ett tillval när du kompilerar vim.

x-versionen tillför en hel del nytt, främst för användare som inte gillar terminalen men även bättre stöd för interaktion med andra gui program och rullninglist Smile

emacs -nw vs. vim och gvim vs. emacs låter mer rättvist tycker jag.