Vinnaren i pepparkakshustävlingen!
2024-02-27, 15:22
  #73
Medlem
Citat:
Ursprungligen postat av DrSvenne
Typfel ska kompilatorn varna för, eller ge ett felmeddelande.
Ingen idé för kompilatorn att tugga vidare om den hittar sådana typfel.
C har ingen typkoll, iaf inte för 10 år sedan när jag senast skrev C. Jag minns vilket lyft det var när C++ blev ett realistiskt alternativ med Borland Turbo C++ (Glockenspiel och liknande C++ -> C transpilers såg jag aldrig som realistiska att använda, dessutom svindyra), för då kunde man kompilera om hela sin C-kodbas med C++-kompilatorn och få den typkollad.

C-kompilatorn accepterade gladeligen att man t ex skickade en int till en funktion som önskade en char* etc. Därför fanns Lint, https://en.wikipedia.org/wiki/Lint_(software) men av bortglömda skäl körde vi aldrig med den.
Citera
2024-02-28, 03:49
  #74
Avstängd
Citat:
Ursprungligen postat av Psychotronix
C har ingen typkoll, iaf inte för 10 år sedan när jag senast skrev C. Jag minns vilket lyft det var när C++ blev ett realistiskt alternativ med Borland Turbo C++ (Glockenspiel och liknande C++ -> C transpilers såg jag aldrig som realistiska att använda, dessutom svindyra), för då kunde man kompilera om hela sin C-kodbas med C++-kompilatorn och få den typkollad.

C-kompilatorn accepterade gladeligen att man t ex skickade en int till en funktion som önskade en char* etc. Därför fanns Lint, https://en.wikipedia.org/wiki/Lint_(software) men av bortglömda skäl körde vi aldrig med den.

??? Då kan man fråga sig vilken kompilator du använde ? Dagens standard brukar luta sig mot gcc.
Annars är standardverket för C The C Programming Language av Kernighan & Ritchie.
Och där står klart och tydligt att C är ett typat högnivåspråk.

Så jag blir misstänksam vilken kompilator du menar ?
Borland Turbo C/C++ är cirka 30 år sedan den lanserades och då var den redan typad.

Det du menar med att man kunde skicka vad som helst som parametrar till en funktion
gäller bara så kallade macron, dvs som inledes med prefixet #define
Macron kan alltså också skrivas som funktioner men har ingen (inbyggd) typkontroll.

Tex som här:
#define MAX(a, b) (a > b ? a : b)

Detta utttryck har alltså ingen typkontroll som kompilatorn kan använda sig av.
Egentligen så lär det finnas förvånande nog många seriösa seniora programmerare som inte förstår
hela preprocessorns fulla potential.

Alla programrader som börjar med # kallas nämligen för preprocessor direktiv,
och de har en egen "hemmakokt syntax" och är inte en del av
programspråket även om många verkar tro det.

Fråga tex Jan Skansholm ?
Om han vill köra en genomgång ?
Det finns många eleganta tricks man kan göra med dessa direktiv.

Det vanligaste är
#include <stdio.h>

I vissa fall använder man casting operatorn, tex (void *) för
att casta till en godtycklig pekare. För att förhindra typkontroll.
Sedan castas den tillbaka till dess rätta typ.

C har de så kallade primitiva datatyperna char , int, float etc
medans de komplexa sammansatta datatyperna heter structs eller mera sällan unions.
FILE är ett såant exempel på en struct.

C hade en egen exceptionmetod och den hette signal, och använde interruptvektorn
i de flesta fall för att avbryta en loop eller hela programmet.
Den förutsatte också att programmeraren vart tvungen att själv skriva koden som skulle
städa upp.

Signal är snabbare än lock_sem, unlock_sem etc eftersom de har en omedelbar respons och att den saknar nästan all overhead.
Om interruptet måste sedan exekvera mycket kod, så blir vinsten liten och man kan
lika gärna använda semaforfunktionerna.

Det är dock knepigt att skriva signalanropen rätt, ibland rekommenderas att använda bägge signals
SIGUSR1 och SIGUSR2

På rätt sätt kan de användas för att synka trådar eller processer.

I Cs barndom så användes dessa signalanrop mest för att stoppa ett
helt träd av processinstanser.
Signalen skickas som en kaskad, (broadcast) nerifrån roten upp till löven.
Eller mera perfekt, det omvända, från löven ner till roten.

Tyvärr verkar det saknas gott om exempelprogram, för de är enkla att använda
och mycket smidiga om städaupp-koden inte blir för klumpig.

En signalHandler som ska fånga ett interrupt kan vanligen inte använda filhantering, för filhanteringen, tex printf som själv kan anropa tyngre rutiner kan också behöva änvända interrupt särskilt mot
stdout, stderr, och stdprn.

Istället brukar man använda ett system med flaggor.
och helt undvika tidsödande filhantering inne i en signalHandler.

Så signalHandler sätter bara en eller flera flaggor , tex int terminera_nu =1;

Här finns ett exempel på en användare som inte vet hur man gör:

https://stackoverflow.com/questions/50446496/c-how-to-correctly-use-sigusr1

Citat:
C - How to correctly use SIGUSR1?
Asked 5 years, 9 months ago
Modified 5 years, 9 months ago
Viewed 17k times

I've googled far and wide and have come across no CLEAR instructions on how to use a user-defined signal (SIGUSR1/SIGUSR2).

Context: I am trying to send a signal within the running process so that once the signal is sent, the signal handler will print a statement to tell the user that the signal has been caught. I have tried to use a signal handler as shown below.

Kod:
void signalHandler(int signalNum) {
  if (signalNum == SIGUSR1) {
    printf("Caught SIGUSR1 signal.\n");
  }
}

/* Call in main as follows */
signal(SIGUSR1, signalHandler);

En mer riktigare kod vore:
Kod:
void signalHandler(int signalNum) {
  if (signalNum == SIGUSR1) {
    printf("Caught SIGUSR1 signal.\n");
    fflush(stdout);
  }
}

Detta beror på att om inte fflush anropet finns direkt efter så hinner städauppsekvensen i
att terminera ett program redan hinner nollställa stdouts buffer

ADA bygger på Simula 67, delvis på grund av mekanismen som heter Rendezvous (mötesplats).
ADA tillförde en massa annat, tex att kolla parametrarnas intervall mm.

ADA har blivit framgångsrikt men eftersom det mest handlar om militära hemligheter, så får vi väl inte se de framstegen heller ?
ADA har väl också exceptions vilket kopierades till C++

Alltså ett mycket smidigt sätt att hoppa ut ur en mycket djup loop.

C++ blev förstås hårdare typat av produktivitetsskäl det gick snabbare att utveckla program
som där det redan i kompileringsfasen blev stopp pga att fel datatyp hade använts.

Den hårdare typningen behövdes pga de alltmer komplexa datatyperna som C++ kunde
hantera.

Både ADA, C och C++ kom att följa både ASCII och POSIX, för att kunna bygga pålitliga program.
Som inte gav BSOD rätt som det var.

POSIX är en mängd regler som ett OS måste behärska för att förhindra att hela systemet kraschar.
Citera
2024-02-28, 14:14
  #75
Medlem
Citat:
Ursprungligen postat av DrSvenne
??? Då kan man fråga sig vilken kompilator du använde ? Dagens standard brukar luta sig mot gcc.
Annars är standardverket för C The C Programming Language av Kernighan & Ritchie.
Och där står klart och tydligt att C är ett typat högnivåspråk.

Så jag blir misstänksam vilken kompilator du menar ?
Borland Turbo C/C++ är cirka 30 år sedan den lanserades och då var den redan typad.
Jag började med MS C (som egentligen var en re-branded Lattice C och inte fullt K&R-compliant i första versionerna) men bytte till Turbo C så fort den kom pga snabbare kompilering och att den hade en IDE. Tyvärr var debuggern ganska kass (minns inte om den öht hade någon) jfrt med MS CodeView men inom något år var Borlands debugger bättre.

Det fanns f ö en allmän uppfattning om att MS C producerade snabbare kod än Turbo C men i praktiken såg vi ingen märkbar skillnad när vi bytte kompilator. Antagligen fanns det prestandaskillnader i vissa benchmarks som vi aldrig kunde märka i produktion.

Nu är det förvisso 34 år sedan jag lämnade C för C++ men jag minns iaf att svalde C typfel som C++ stoppade. Det var ett av skälen till varför Lint fanns.

När parametriserade typer (templates) infördes i C++ blev det ytterligare ett typsäkerhetslyft.

Jo, jag är väl bekant med hur macro-expansion fungerar...
Citera
2024-02-28, 16:52
  #76
Avstängd
Citat:
Ursprungligen postat av Psychotronix
Jag började med MS C (som egentligen var en re-branded Lattice C och inte fullt K&R-compliant i första versionerna) men bytte till Turbo C så fort den kom pga snabbare kompilering och att den hade en IDE. Tyvärr var debuggern ganska kass (minns inte om den öht hade någon) jfrt med MS CodeView men inom något år var Borlands debugger bättre.

Det fanns f ö en allmän uppfattning om att MS C producerade snabbare kod än Turbo C men i praktiken såg vi ingen märkbar skillnad när vi bytte kompilator. Antagligen fanns det prestandaskillnader i vissa benchmarks som vi aldrig kunde märka i produktion.

Nu är det förvisso 34 år sedan jag lämnade C för C++ men jag minns iaf att svalde C typfel som C++ stoppade. Det var ett av skälen till varför Lint fanns.

När parametriserade typer (templates) infördes i C++ blev det ytterligare ett typsäkerhetslyft.

Jo, jag är väl bekant med hur macro-expansion fungerar...

Den enda osäkra funktionerna var printf-familjen, där har du rätt att C svalde typfel utan vidare, men sådan dokumentation fanns redan då. Om hur printf fungerade.
Om att man bör vara mycket observant att rätt parameter skickas till respektive %-expander.
Och ett problem för alla funktioner som har ett variabelt antal parametrar.
%-expanderkommandot gör nämligen ingen typkontroll.
Eftersom det inte kan göras i runtime (*)
Det finns säkert 1000-tals artiklar om säkerhetsproblemen med printf-familjen,
och många förslag till lösningar förstås.

C++ löste det med sina stream-klasser, och som också kom att identifiera och skilja C++ från C.
Men du skrev 10 år sedan ?
Lite väl svårt att bygga vettiga program med Borland Turbo C/C++
Det förutsätter att du har en fungerande DOS-emulator för 16-bit.
Inte särskilt användbart idag, nej....
Windows 7 32-bit var väl den sista som hade kvar nästan hela stödet för 16-bit ?

Äh skit samma, du kan hitta rätt gammal C-kod för *nix som du kan kompilera på *nix familjen,
dvs Unix/Linux och själv se att kompilatorn ska bryta direkt vid något typfel.
Även om du hittar någon gammal version av gcc ?

Symantec C++ och Watcom C++ fanns också.

Alla kompilatorer som följde standard C ansågs vara kompatibla, och säkerheten mot typfel fanns noga dokumenterat. Och det var upp till programmeraren att hålla kontroll på.
Benchmarks är beroende av tex både hårdvara och OS, plus ifall många processer körs samtidigt på samma system.

Det har funnits många olika sidospår inom datavärlden, varav en del sidospår tyvärr har dött ut.
Tex 36-bits maskiner som körde 6-bits ASCII, som bara gav utrymme för 64 olika tecken, tex DECs TOPS-20:
https://en.wikipedia.org/wiki/36-bit_computing

36 bits var den Holy Grail man hade letat efter då, eftersom de 36-bitarna kunde representera upp till ett 10-siffrigt decimalt tal.
Som var nödvändigt i många ekonomiska, tekniska och vetenskapliga sammanhang.

Apples Swift gör tvärtom och skippar visst typkontroll helt vid kompilering, och parametrar skickas som i ett packat message, typ en struct som den anropade funktionen sedan får parsa självt.
Analogt med WM_MESSAGEs i Windows.

(*) Här får du konsultera dokument som beskriver hur assemblerkod exekveras i runtime.
Och hur parametrar hanteras.
Det finns givetvis metoder att kringgå detta med att skippa alla primitiva datatyper (tex char, int, bool, float etc), och att varje variabel istället får bestå av två delar, dels en byte som talar om vilken typ den har, och resten av bytes är variabeln.
Finns förklarat i diverse papers om att öka datasäkerheten.
Finns massor av intressanta datateoretiska diskussioner om vad information egentligen är..

Givetvis blir en sådan full implementering i hårdvara en grymt kostsam investering som knappast
kan motiveras i dagsläget.
Man kommer då att få stora problem att debugga sådana program, på ett vettigt sätt.
__________________
Senast redigerad av DrSvenne 2024-02-28 kl. 17:19.
Citera
2024-02-29, 06:42
  #77
Medlem
Stig-Britts avatar
Citat:
Ursprungligen postat av Tigaz
Hej alla! Jo, jag har börjat en utbildning, jag är 35 går från ett industrijobb som jag haft i 14 år, har alltid velat komma bort därifrån och valde att satsa på studier, en vän sa att han tyckte jag skulle kika på ett program som "mjukvaruutvecklare inom industriell iot" eftersom han tyckte jag passade som det(har intresse för datorer, men aldrig kodat) eller jo! För 18 år sedan när jag gick programmering a och b(pascal tiden) dock kikade jag på min kompis och fattade inte något, och fick ändå g.. Sjukt. Men iaf, redo att prova och första kursen var skitlätt(projektkunskap 50p av 50 möjliga) nu har jag börjat med c och visst har jag gjort framsteg, men jag fattar ändå NOLL känns det som. Detta får mig att börja tvivla på mig väldigt mycket "gör en funktion som säger jämför en char[] och skriver ut om det är en palidrom(namn som skrivs baklänges blir lika som framlänges.. Ja jag vet inte, jag är helt nollad, just nu känns det som att alla kan allt i kursen, jag är sämst jag fattar noll kan ingenting. (har suttit och programmerat 210 timmar på 3 veckor. Varje dag minst tio timmar/dag har 3 barn och är helt slut på kvällarna, ska det vara såhär svårt? Mvh mig.

För att bli duktig på programmering så är det inte i första hand att programmera man ska fokusera på. Det vore ungefär som att fokusera på hur man använder en hammare för att bli duktig snickare. AI kan skriva kod också - det är inte där ditt värde kommer finnas.

Hammaren är ett av flera verktyg som en snickare använder, precis som att programmeringskod är ett av flera verktyg som en programmerare använder sig av. Släpp du själv kodandet lite, eller håll åtminstone isär det från din ansats att bli programmerare.

Det finns några bra baskunskaper som man har nytta av som programmerare, så som algoritmik, logik, fysik, matematik, kreativitet och lite annat. Vill man bli duktig som programmerare så behöver man kunna ta komplexa problem, abstrahera dessa och bryta ner dem i beståndsdelar. Här är AI för övrigt usel, varför jag inte tror att AI kommer ersätta programmerare (utöver de mest juniora).

Du löser inte problemet (konceptuellt) genom att skriva kod. Koden skriver du när du har löst problemet (sanning med modifikation när man är lite mer erfaren); du måste först veta vad du vill åstadkomma. I ditt exempel; hur kan man abstrahera frågan "är <text> ett palindrom"?

Vilka beståndsdelar finns det att jobba med? Meningar? Ord? Tecken? Vad är den minsta beståndsdelen som är relevant för problemet, och hur kan vi använda den för att ta reda på om något är ett palindrom? Utgår vi från att en text är palindrom tills motsatsen bevisats, eller tvärtom? Varför?

När du formulerat en metod för att ta reda på om en textsträng är ett palindrom eller inte, så börjar du skriva koden. Precis som att en snickare tar fram hammaren när han vet vad han vill bygga. Hammaren talar inte om vad lösningen är, precis som att koden inte gör det.

Detta är ett sätt att tänka kring världen som tar decennier att bli duktig på, men när du väl förstår tänket så kan du bli tillräckligt duktig för att lösa enklare problem inom loppet av veckor eller månader (olika beroende på person).
Citera
2024-02-29, 09:39
  #78
Medlem
EnergizerBunnys avatar
Citat:
Ursprungligen postat av Tigaz
Hej, nope ingen onlinekurs, kör en yh utbildning mjukvaruutvecklare inom industriell iot.

Hur har det gått med dina studier? Är du färdigutbildad nu?
Citera
2024-02-29, 17:49
  #79
Medlem
Det här kanske kan lära dig saker och hjälpa dig att förstå bättre:

En variabel är en minnesadress. Den är betecknad som en symbol i en symboltabell, men är i grund och botten en minnesadress som kan innehålla olika värden.

Ett exempel:
Kod:
int a = 1;
Variabeln a, här, symboliserar en minnesadress, och tecknet "a" sparas sedan ingenstans förutom på vissa ställen som till exempel debug-info.

Lär dig type casting och pointer conversions.

Med en pekare kan man peka på direkta adresser som t. ex:
Kod:
char* video_memory = (char*)0xb8000;
.

Med pointer conversions kan du lättare greppa saker som man gör innan polyformism. Om du har en basklass (base_class) och en av den ärvd klass (derived_class) så kan delar av en kod se ut såhär:
Kod:
base_object = derived_object;
, vilket är samma sak som
Kod:
base_object = (class base_class*)derived_object; 
.

Lär dig x86 Assembly.

Allt detta ska man nog helst brinna för/tycka att det är jätteskoj att lära sig och hålla på med.
Tycker du att det är skoj att lära dig och hålla på med kod och datavetenskap så kör på.
Citera
2024-03-04, 00:20
  #80
Medlem
BekraftadNegers avatar
En kul uppgift som ger en bra grundförståelse!

Kod:
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int isPalindrome(char *str) {
    int i = 0, j = strlen(str) - 1;
    while (i < j) {
        while (!isalpha(str[i]) && i < j) i++;
        while (!isalpha(str[j]) && i < j) j--;
        if (tolower(str[i++]) != tolower(str[j--])) return 0;
    }
    return 1;
}

int main() {
    char str[100];
    printf("Ange en sträng: ");
    fgets(str, sizeof(str), stdin);
    str[strcspn(str, "\n")] = '\0';
    printf("%s är %set palindrom.\n", str, isPalindrome(str) ? "" : "inte ");
    return 0;
}
Citera
2024-03-05, 12:22
  #81
Medlem
Citat:
Ursprungligen postat av DrSvenne
Den enda osäkra funktionerna var printf-familjen, där har du rätt att C svalde typfel utan vidare, men sådan dokumentation fanns redan då. Om hur printf fungerade.
Om att man bör vara mycket observant att rätt parameter skickas till respektive %-expander.
Och ett problem för alla funktioner som har ett variabelt antal parametrar.
Med typfel menar jag inte va_list / va_start eftersom den typen är precis vad man förväntar sig: en pekare till en hög bytes på stacken.

Citat:
Ursprungligen postat av DrSvenne
C++ löste det med sina stream-klasser, och som också kom att identifiera och skilja C++ från C.
Men du skrev 10 år sedan ?
Lite väl svårt att bygga vettiga program med Borland Turbo C/C++

Det förutsätter att du har en fungerande DOS-emulator för 16-bit.
Inte särskilt användbart idag, nej....
Windows 7 32-bit var väl den sista som hade kvar nästan hela stödet för 16-bit ?
1) Det jag använde för ca 10 år sedan var MS C, dock inte för något annat syfte än att återskapa Petzolds gamla Windows 1.0-demo som en kul grej eftersom den fyllde 35 då. Kul med parameternamn som påminner om hur "kul" det var med segmenterad minnesmodell...
2) Turbo C++ var inget DOS-program förutom under de första åren. Fr 1992 var det ett Windows-prog och det var möjligen också då det bytte officiellt namn till Borland C++. Debuggern var fortfarande ett konsol-program, dock inte DOS. Sista Win-versionen jag körde det på var Win2000 och då var det i praktiken redan dött sedan ett par år: QA hade blivit kass, Hejlsberg hade lämnat för MS och MS körde limousiner till Borlands kontor och lockade Borlands utvecklare till anställningsintervjuer.
Citera
2024-03-05, 23:58
  #82
Avstängd
Citat:
Ursprungligen postat av Psychotronix
Med typfel menar jag inte va_list / va_start eftersom den typen är precis vad man förväntar sig: en pekare till en hög bytes på stacken.


1) Det jag använde för ca 10 år sedan var MS C, dock inte för något annat syfte än att återskapa Petzolds gamla Windows 1.0-demo som en kul grej eftersom den fyllde 35 då. Kul med parameternamn som påminner om hur "kul" det var med segmenterad minnesmodell...
2) Turbo C++ var inget DOS-program förutom under de första åren. Fr 1992 var det ett Windows-prog och det var möjligen också då det bytte officiellt namn till Borland C++. Debuggern var fortfarande ett konsol-program, dock inte DOS. Sista Win-versionen jag körde det på var Win2000 och då var det i praktiken redan dött sedan ett par år: QA hade blivit kass, Hejlsberg hade lämnat för MS och MS körde limousiner till Borlands kontor och lockade Borlands utvecklare till anställningsintervjuer.

Segmenterad minnesmodell fanns där av en högst påtaglig anledning, hårdvaran såg ut så med 16 bitars arkitektur. Segment : offset metoden användes, det fanns långa och kortare pekare. En kort pekare hade 16 bits och kunde bara adressera 64 KB i taget. Detta var inget problem så länge man höll sig inom 64 KB. Men skulle man ha pekararitmetik som kunde överskrida in på nästa intilliggande fragment/segment, fick man vara jättenoga med vad man gjorde.
En del smarta macros fanns för detta ändamål.
Ja, det fanns parameternamn som var short pointers och long pointers. Long pointers brukade förkortas senare LPTSTR som prefix i namnet.

Debuggern var byggd i Turbo Vision ett character based GUI, ungefär som gamla edit.exe eller de första notepad.

Borland C++ gav ut OWL Object Windows Library, som hade vissa påtagliga skillnader mot MFC.
OWL hade en betydligt bättre objektorienterad design än MFC hade.

MFC var enkla wrappers runt de redan utgivna fönsterhanteringsfunktionerna som
var ursprungligen skrivna i C av Microsoft.

Både MFC och OWL fick en konstig nackdel, nämligen att virtuella klasser om de var för djupt virtualiserade rekursivt de fick en rätt rejäl prestandaförlust. Något som man försökte undvika med att definiera macron för objektmetodernas anrop som sedan expanderades vid kompilering.

En metod att fuska med objektorienteringens designfilosofi alltså.
Något som Stroustrup inte tycks ha förutsett tillräckligt.
Att förlusten var tydligt märkbar i ett fönsterhanteringssystem som Windows.

Detta blev ett mycket omtalat problem, och fick bland annat Linus Torvalds att gå ut att C++ kommer inte att prestandamässigt kunna slå C, någonsin.

Citat:
Ursprungligen postat av Psychotronix
1) Det jag använde för ca 10 år sedan var MS C, dock inte för något annat syfte än att återskapa Petzolds gamla Windows 1.0-demo som en kul grej eftersom den fyllde 35 då. Kul med parameternamn som påminner om hur "kul" det var med segmenterad minnesmodell...

Nej det var inget kul, men visste man vad man gjorde så gick det att begripa det ändå. De hade inget annat val, eftersom hårdvaran var organiserad på det viset.

En stor nackdel var att skärmarna bara visade 640x480 man fick knappt plats med koden på en skärmsida. 32-bit blev en enorm förändring, plötsligt fanns det stora möjligheter till att producera välskrivna program.
Citera
2024-03-06, 00:06
  #83
Jag tycker det är nice att det finns folk som vill hålla på att koda.
Så internet hemsidorna fungerar

Tack för erat arbete
Citera
2024-03-06, 00:09
  #84
Medlem
Det är dött.
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in