
English: 
Shalom!
I am Bisqwit, and a moment ago I thought of
something interesting about switch-cases in C.
 
Now, I have discussed the
curious properties of C and C++ switch-cases
before, in my videos,
but maybe you haven't watched those videos yet.
In any case, it is such an interesting topic
that it is worth discussing some more.
This here is a very simple example C++ program
featuring the switch-case statement.
As you can see, it chooses an action
based on the input value.
This is elementary knowledge.
However, what comes as a total surprise to
most C and C++ programmers,
even some experts, is the exact nature of
the switch-case statement.
Unlike in many other languages,
such as BASIC or PHP,
the structure of the switch-case statement
is not very rigid.
The case-labels actually
do not necessarily need to be

Finnish: 
Shalom!
Olen Bisqwit, ja joku aika sitten mieleeni
tuli seikka liittyen C-kielen switch-caseihin.
 
Olen käsitellyt C- ja C++ -switch-case
-rakenteiden mielenkiintoisia ominaisuuksia
aiemminkin videoissani,
mutta ehkä et ole vielä nähnyt niitä.
Joka tapauksessa se on sen verran mielenkiintoinen aihe,
että sitä sopii tutkia lisääkin.
Tämä on sangen yksinkertainen C++-ohjelma,
joka käyttää switch-case -rakennetta.
Kuten näkyy, se valitsee toiminnon
riippuen syötearvosta.
Tämähän on perusasioita.
Mutta mikä tulee yllätyksenä useille
C- ja C++ -ohjelmoijille,
jopa asiantuntijoille, on kyseisen
rakenteen tarkka luonne.
Toisin kuin monissa muissa kielissä,
kuten BASIC tai PHP,
switch-case -lauseen rakenne ei ole
kovin jäykkä.
Case-lauseiden ei välttämättä
tarvitse olla

Finnish: 
suoraan switch-lauseen sisällä, vaan ne
voivat olla toisten lauseiden sisällä.
Case toimii siis monessa suhteessa samoin
kuin ne labelit, joita käytetään goton kanssa.
Tätä voi soveltaa monella jännällä tavalla.
Hyppään nyt toiseen aiheeseen.
BASIC oli ensimmäinen ohjelmointikieleni,
jonka opin. Siinä oli siisti komento
nimeltä GOSUB, josta tykkäsin.
 
Jos GOTO-lausetta voi verrata
konekielen JMP-käskyyn,
GOSUB-lausetta voi verrata
konekielen CALL- tai JSR -käskyihin.
Se hyppää kohteeseen, mutta myös sallii
myöhemmin palaamisen (RETURN) seuraavaan käskyyn.
Kun vaihdoin proseduraalisiin
kieliin kuten Pascal ja C,
GOSUB oli yksi niistä käskyistä,
joita monesti kaipasin.
Tässäpä kysymys: Voiko GOSUBin
jotenkin toteuttaa C++:lla?
Ymmärrän toki, että rakenteelliset
funktiot ja proseduurit
ovat paljon nätimpi ratkaisu
aliohjelmiin kuin GOSUB ikinä oli.

English: 
at the top level inside the switch-case statement.
They can be nested inside other control blocks.
Basically, the cases are much like those labels
that you could use with the goto statement.
This allows for many fascinating constructs.
Now I will jump to another topic.
BASIC was the first programming language
that I learned. It had this cool command
called GOSUB, which I loved.
 
If the GOTO statement is equivalent to the
assembler JMP instruction,
the GOSUB statement is equivalent to the assembler
CALL or JSR instructions.
It jumps to the target, but also allows later
RETURNing to the next instruction.
When I switched to procedural
languages like Pascal and C,
GOSUB was one of those commands
that I much wanted to have.
Now, here's the question: Could we
 implement GOSUB somehow in C++?
Now I understand of course that structural
procedures and functions
are a much cleaner solution to sub-routines
than GOSUB ever was.

Finnish: 
Siitä huolimatta tunnen vielä
nostalgiaa GOSUB-käskyä kohtaan.
Kuvitellaanpa että jostain syystä
tarvitsemme GOSUB-käskyn C:ssä tai C++:ssa.
Miten se toteutettaisiin?
C-ohjelmoijat saattavat ajatella setjmp/longjmp
-funktioita, mutta en tykkää niistä kahdesta
joten keksin jotain muuta.
GCC:ssä on C-kielen laajennus, jolla
goto-labelin osoitteen voi laskea.
Tämä GNU-laajennus on yksi tavoista,
joilla GOSUB voidaan toteuttaa C++:ssa.
Myönnän, että sanon välillä C,
ja välillä C++,
mutta käytännössä kirjoitan C:tä,
paitsi niissä kohdin joissa
käytän C++:n STL-kirjastoa, jottei
minun tarvitse kirjoittaa
valtavasti malloc- ja free -sisältöistä
koodia aina kun käytän tietorakenteita,
joissa en halua olevan kiinteä kokorajoitus.
No niin. Tämän GNU C -laajennoksen
avulla RETURN-lauseessa

English: 
Nevertheless, I still feel some nostalgic
love towards the GOSUB command.
Suppose we really wanted to have GOSUB in
C or C++ for some reason.
How would we implement it?
Now C programmers might think of the setjmp/longjmp
functions, but I don't like those two functions
so I'll think of something else.
In GCC there is an extension to C language
which allows taking the address of a goto
label.
This GNU extension gives one of the possible
ways
to implement the GOSUB instruction in C++.
Now I realize I am saying C in one sentence
and C++ in the other,
but basically I'm writing C here, except for
the parts where I rely
on the C++ standard template library,
that relieves me from writing tons of code
involving malloc and free
every time I'm dealing with
data structures where I don't want to have
a fixed size limit.
So anyway. With this GNU C extension,
implementing the RETURN statement involves

English: 
popping from a stack a void pointer,
representing the return location,
and jumping to that location.
Conversely, the GOSUB instruction pushes the
return address into the stack,
and jumps to the target address.
Because this GOSUB macro can be issued many times,
but labels are normally global to the whole function,
we use this GNU C extension which allows defining local labels.
 
Mind you, this "stack" we are talking about
here is not the hardware stack.
It is a data structure, for example a double-ended
queue or a linked list.
It could be any data structure as long as
it does not intervene with how
the compiler itself assumes the hardware stack
is used.
A compiler-dependent solution is not what
I had in mind though.
Is there a way to do this in standard C?
Turns out there is. Let's get back to our
switch-case topic from earlier.
Remember how we learned that the "case" statements
in a switch-case

Finnish: 
popataan pinosta void-osoitin,
joka kuvaa paluukohdetta,
jonne hypätään.
Vastaavasti GOSUB-lause työntää
paluuosoitteen pinoon,
ja hyppää kohdeosoitteeseen.
Koska GOSUB-käskyä voi käyttää monta kertaa,
mutta labelit ovat globaaleja koko funktiossa,
käytän tätä GNU C -laajennosta joka mahdollistaa
paikallisten labelien määrittelyn.
 
Kannattaa huomata, etten puhu tässä
nyt CPU:n omasta "pinosta".
Kyse on tietorakenteesta, esimerkiksi
kaksisuuntainen jono tai linkattu lista.
Se voisi olla mikä tahansa tietorakenne,
kunhan se ei sotke sitä miten
kääntäjä itse olettaa, että CPU:n pinoa käytetään.
Kääntäjästä riippuva ratkaisu ei kuitenkaan ole se, mihin tähtäsin.
Voiko GOSUBin toteuttaa standardi-C:llä?
Nähtävästi voi. Palataanpa nyt
siihen switch-case -aiheeseen.
Muistammehan miten "case"-lauseet
switch-casessa voidaan

Finnish: 
sijoittaa minkä tahansa rakenteen sisälle?
Jos kiedomme koko ohjelman switch-caseen,
koko ohjelmasta tulee alue, jossa voidaan
hypätä tiettyyn sijaintiin käyttämättä "goto"-lausetta.
Pinossa ei enää tallenneta osoittimia,
vaan pelkkiä kokonaislukuja,
jotka switch-case -rakenne muuttaa
ohjelman sijainneiksi.
RETURN-toteutuksessa popataan numero pinosta,
ja syötetään se switch-lauseelle.
Tässä tarvitaan yksi "goto" jotta päästään takaisin.
For-silmukka toimisi myös, mutta "goto" on
vankempi eikä sitä haittaa erilaiset
ohjausrakenteet, jotka muuten
saattaisivat napata hyvää tarkoittavan
"break"- tai "continue"-lauseen omaan käyttöönsä.
 
Switch-lauseelle annettava kokonaisluku
muodostetaan senhetkisestä rivinumerosta.
Tämä valitettavasti tarkoittaa, ettei
voi olla kuin yksi GOSUB riviä kohti,
pieni haitta tässä menetelmässä.

English: 
can be nested inside any control structures?
If we wrap our whole program inside a switch-case,
the whole code becomes a region where we can
jump to some particular location without actually
using "goto".
Now the stack will no longer store pointers
of any kind,
but simple integers, which are translated
by the switch-case
into program locations.
In the RETURN implementation, we pop a number
from the stack,
and feed it to the switch statement.
We do need one "goto" for re-entering the switch.
A for-loop would also work, but a "goto" is
more robust
against surrounding control structures that
might inadvertedly intercept any
well-intentioned "break" or "continue" statements.
 
The actual integer used as a key in the switch-case
is created from the current line number.
This unfortunately means that there can be
only one GOSUB statement per line, a minor
shortcoming in this method.

English: 
Now, to compile the program.
It works of course.
Otherwise there would be little point to this video!
To drive the point home that this is indeed
standard-compliant code,
let's use a different compiler and very strict
compatibility options.
There.
I believe that seeing this kind of source code
can inspire programmers to think outside the box,
and to find new joy in their chosen tools.
Always strive to do at least some things differently.
That is how you learn.
Now here's what the BASIC program you saw
earlier actually does.
I wrote this program somewhere in 1993, when
it had been less than a year
when I began programming. Yesterday I just
rewrote the program to make it
better for showcasing in a video.
Maybe you should not use the GOSUB trick
in your code, but this was more to the point
a story device to drive home a larger lesson.
If a programmer does not have fun programming,
what good

Finnish: 
Sitten käännetään ohjelma.
Se toki toimii.
Eihän tässä videossa muuten olisi mitään järkeä!
Jotta tulisi selväksi, että tämä tosiaan
on standardin mukaista koodia,
käännän tämän ohjelman vielä toisella
kääntäjällä jyrkin yhteensopivuusoptioin.
Noin. Uskon, että tällainen ohjelmakoodi
voi inspiroida ohjelmoijia ajattelemaan uusin tavoin,
ja löytämään uutta intoa omien työkalujensa kanssa.
Aina tulee pyrkiä tekemään ainakin jotain toisin.
Sillä tavoin oppii.
Nyt käynnistän aiemmin näyttämäni BASIC-ohjelman.
Kirjoitin tämän ohjelman joskus 1993,
kun olin ohjelmoinut
vasta alle vuoden. Eilen vaan kirjoitin
ohjelman uusiksi, tehdäkseni siitä
paremman videoesitystä varten.
Ehkä GOSUB-temppua ei tulisi käyttää omissa
ohjelmissa, mutta pointti tässä oli nyt
enemmänkin tietyssä opetuksessa.
Jos ohjelmoija ei iloitse ohjelmoimisestaan,

Finnish: 
mitä hyötyä on olla ohjelmoija ensinkään?
Uskon, että ennen kaikkea ohjelmointi on taidetta.
Joidenkin mielestä ohjelmointi on tiedettä.
Uskon että se on väärinkäsitys.
Psykologia voi auttaa selittämään
kuvataiteen ja musiikkitaiteen
luomista ja nauttimista.
Tietokonetiede voi auttaa selittämään
ohjelmointitaiteen luomista
ja sen suorittamista.
Kaikkiin taiteisiin liittyy säännöt
ja käytännöt, mutta taiteilijan
tulee olla valmis murtautumaan ulos
noista rajoituksista,
jos tämä haluaa kehittyä.
Mutta ensinnäkin tulee tietää, miksi nämä
säännöt ja käytännöt ovat olemassa.
Jos sääntöjä ei ymmärrä, eikä
niitä noudata, tuloksena syntyy vain
epämääräistä sotkua, jota
tuskin voi luokitella taiteeksi.
Siispä ensin opettele säännöt, ja sitten
riko niitä taiteellisesti. Siinä opetukseni!
Kiitos katsomisesta!
Muistathan tilata kanavani!

English: 
does it do for oneself to be a programmer
in the first place?
I believe that foremostly, programming is
an art.
Some people believe that programming is a
science.
In my opinion, that is a misnotion.
Psychology can help explain the processes
involving in the
creation and consumption of graphical art
or musical art.
Computer science can explain the processes
involving in the
creation and execution of programming art.
All arts are governed by rules and conventions,
but an artist
must also be ready to break free from those
constraints,
if they wish to develop.
First, however, you must know why those rules
and conventions exist.
If you do not understand the rules and you
refuse to walk
by them, the only thing you create is
an unsightly mess, which hardly qualifies as art.
So, first learn the rules, and then break
them artistically. That is my lesson!
Thank you for watching!
Don't forget to Go Sub my channel!
