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.