Vstupní bod - Entry point
V počítačovém programování je vstupním bodem bod v programu, kde začíná provádění programu a kde má program přístup k argumentům příkazového řádku .
Chcete-li spustit program v provedení , na nakladač nebo operační systém předá řízení jeho vstupní bod. (Během bootování je samotným operačním systémem program). To označuje přechod z doby načítání (a doby dynamického odkazu , pokud je k dispozici) do doby běhu .
U některých operačních systémů a programovacích jazyků je vstupní bod v běhové knihovně , sadě podpůrných funkcí pro jazyk. Kód knihovny inicializuje program a poté předá řízení správnému programu. V ostatních případech může program inicializovat samotnou běhovou knihovnu.
V jednoduchých systémech spuštění začíná prvním příkazem, který je běžný v interpretovaných jazycích , jednoduchých spustitelných formátech a zavaděčích . V ostatních případech je vstupní bod na jiné známé adrese paměti, kterou může být absolutní adresa nebo relativní adresa ( offset ).
Alternativně může spuštění programu začít v pojmenovaném bodě, buď konvenčním názvem definovaným programovacím jazykem nebo operačním systémem, nebo názvem specifikovaným volajícím. V mnoha jazycích rodiny C se jedná o funkci pojmenovanou main
; v důsledku toho je vstupní bod často známý jako hlavní funkce .
V jazycích JVM, jako je Java, je vstupním bodem statická metoda pojmenovaná main
; v jazycích CLI, jako je C #, je vstupním bodem statická metoda s názvem Main
.
Používání
Vstupní body platí jak pro zdrojový kód, tak pro spustitelné soubory. Při každodenním vývoji softwaru však programátoři zadávají vstupní body pouze ve zdrojovém kódu, díky čemuž jsou mnohem lépe známí. Vstupní body ve spustitelných souborech závisí na binárním rozhraní aplikace (ABI) skutečného operačního systému a jsou generovány kompilátorem nebo linkerem (pokud nejsou ABI opraveny). Jiné propojené soubory objektů mohou mít také vstupní body, které linker použije později při generování vstupních bodů spustitelného souboru.
Vstupní body jsou schopné předávat argumenty příkazu, proměnné nebo jiné informace jako lokální proměnnou používanou Main()
metodou. Tímto způsobem lze nastavit konkrétní možnosti při spuštění programu a poté je program interpretovat. Mnoho programů to používá jako alternativní způsob konfigurace různých nastavení nebo provádění různých akcí pomocí jednoho programu.
Moderní
Ve většině dnešních populárních programovacích jazyků a operačních systémů má počítačový program obvykle pouze jeden vstupní bod .
V programech C , C ++ , D , Zig , Rust a Kotlin se jedná o funkci s názvem main
; v Javě je to statická metoda s názvem main
(ačkoli třída musí být zadána v době vyvolání) a v C # je to statická metoda s názvem Main
.
V mnoha hlavních operačních systémech má standardní spustitelný formát jediný vstupní bod. V spustitelném a propojitelném formátu (ELF), který se používá v systémech Unix a Unix, jako je Linux , je vstupní bod uveden v e_entry
poli hlavičky ELF. V GNU Compiler Collection (gcc) je vstupním bodem použitým linkerem _start
symbol. Podobně ve formátu Portable Executable , který se používá v systému Microsoft Windows , je vstupní bod určen AddressOfEntryPoint
polem, které se dědí z COFF . V souborech COM je vstupní bod na pevném posunu 0100h.
Jedinou výjimkou z paradigmatu jednoho vstupu je Android . Aplikace pro Android nemají jediný vstupní bod - neexistuje žádná speciální main
funkce. Místo toho mají základní komponenty (aktivity a služby), které může systém načíst a spustit podle potřeby.
Občas používanou technikou je fat binary , která se skládá z několika spustitelných souborů pro různé cíle zabalených do jednoho souboru. Nejčastěji je to implementováno jediným celkovým vstupním bodem, který je kompatibilní se všemi cíli a větvemi vstupního bodu specifického pro daný cíl. Alternativní techniky zahrnují ukládání samostatných spustitelných souborů do samostatných vidlic , každý s vlastním vstupním bodem, který je poté vybrán operačním systémem.
Historický
Historicky a v některých současných starších systémech , jako jsou VMS a OS / 400 , mají počítačové programy velké množství vstupních bodů , z nichž každý odpovídá různým funkcím programu. Obvyklým způsobem, jak označit vstupní body, jak se používají v celém systému ve VMS a v programech PL / I a MACRO , je připojit je na konec názvu spustitelného obrazu , odděleného znakem dolaru ($), např directory.exe$make
.
Počítač Apple I to do jisté míry také používal. Například alternativní vstupní bod v BASIC společnosti Apple I by udržel program BASIC užitečný, když bylo omylem stisknuto tlačítko reset.
Výstupní bod
Obecně platí, že programy mohou kdykoli ukončit návratem do operačního systému nebo selháním . Programy v interpretovaných jazycích vracejí řízení tlumočníkovi, ale programy v kompilovaných jazycích se musí vrátit do operačního systému, jinak bude procesor jednoduše pokračovat v provádění i po skončení programu, což bude mít za následek nedefinované chování .
Obvykle není v programu zadán jediný výstupní bod. V jiných případech však runtime zajišťuje, že programy vždy končí strukturovaným způsobem prostřednictvím jediného výstupního bodu, který je zaručen, pokud samotný runtime nepadne; to umožňuje spustit čisticí kód, například atexit
obslužné rutiny. To lze provést buď vyžadováním toho, aby programy byly ukončeny návratem z hlavní funkce, voláním konkrétní funkce ukončení, nebo runtime chytáním výjimek nebo signálů operačního systému.
Programovací jazyky
V mnoha programovacích jazycích je main
funkcí místo, kde program zahájí provádění. Umožňuje organizaci funkcí na vysoké úrovni a obvykle má přístup k argumentům příkazů daným programu, když byl spuštěn.
Hlavní funkce je obecně první programátorem napsaná funkce, která se spustí při spuštění programu a je vyvolána přímo z inicializace specifické pro systém obsažené v běhovém prostředí ( crt0 nebo ekvivalent). Některé jazyky však mohou spouštět uživatelem psané funkce před hlavními běhy, například konstruktory globálních objektů C ++ .
V jiných jazycích, zejména v mnoha tlumočených jazycích , provádění začíná prvním příkazem v programu.
Následuje neúplný seznam programovacích jazyků, který popisuje jejich způsob definování hlavního vstupního bodu:
APL
V APL je při načtení pracovního prostoru obsah proměnné „quad LX“ (latentní výraz) interpretován jako výraz APL a spuštěn.
C a C ++
V C a C ++ , je funkční prototyp z hlavních funkčních vypadá jako jeden z následujících:
int main(void);
int main();
int main(int argc, char **argv);
int main(int argc, char *argv[]);
int main(int argc, char **argv, char **env);
// more specifically in C
// NOT according to the ISO C standard 5.1.2.2.1
// BUT in embedded programming depending on the µC, this form is also used
void main (void);
Hlavní funkce vypadá jako vstupní bod pro programátory aplikací (vstupní bod aplikace nebo hlavní vstupní bod). Programování systému odhalí více informací o programu a specifikuje vstupní bod jinde (v inicializační proceduře nebo v resetování vektoru přerušení pro samostatné programy).
Tyto parametry argc
, počet argumentem , a argv
, argument, vektor , respektive uveďte počet a hodnoty programu argumenty příkazového řádku . Názvy argc
a argv
může být jakýkoli platný identifikátor v jazyce C, ale je běžnou konvencí používat tyto názvy. V C ++ je třeba názvy brát doslovně a „void“ v seznamu parametrů je třeba vynechat, pokud je požadována přísná shoda. Jiné formáty závislé na platformě jsou také povoleny standardy C a C ++, kromě toho, že v C ++ musí být vždy návratový typ int
; Například, Unix (i když ne POSIX.1 ) a Windows mají třetí argument dává programu v prostředí , jinak přístupné prostřednictvím getenv
v stdlib.h
:
int main(int argc, char **argv, char **envp);
Operační systémy založené na Darwinu , jako je macOS , mají čtvrtý parametr obsahující libovolné informace poskytované OS, například cestu k provádějícímu binárnímu souboru:
int main(int argc, char **argv, char **envp, char **apple);
Hodnota vrácená z hlavní funkce se stává stavem ukončení procesu, ačkoli standard C připisuje specifický význam pouze dvěma hodnotám: EXIT_SUCCESS
(tradičně 0) a EXIT_FAILURE
. Význam dalších možných návratových hodnot je definován implementací. V případě, že programátor nedefinuje návratovou hodnotu, kompilátor vloží implicitní return 0;
na konci main()
funkce; toto chování je vyžadováno standardem C ++.
Je zaručeno, že argc
je nezáporné a to argv[argc]
je nulový ukazatel . Podle konvence jsou argumenty příkazového řádku specifikovány argc
a argv
zahrnují název programu jako prvního prvku, pokud argc
je větší než 0; pokud uživatel zadá příkaz „ rm file
“, prostředí inicializuje rm
proces pomocí argc = 2
a argv = {"rm", "file", NULL}
. Stejně argv[0]
jako název, pod kterým se procesy objevují ps
, top
atd., Některé programy, jako jsou démoni nebo programy běžící v tlumočníkovi nebo virtuálním stroji (kde argv[0]
by byl název spustitelného souboru hostitele), se mohou rozhodnout změnit svůj argv tak, aby poskytoval více popisné argv[0]
, obvykle prostřednictvím exec
systémového volání.
main()
Funkce je zvláštní; normálně to musí každý program C a C ++ definovat přesně jednou.
Pokud je deklarováno, main()
musí být deklarováno, jako by to mělo externí propojení; nelze jej deklarovat static
nebo inline
.
V jazyce C ++ main()
musí být v globálním oboru názvů (tj. ::main
), Nemůže být přetížen a nemůže být členskou funkcí , i když název není jinak vyhrazen a může být použit pro členské funkce, třídy, výčty nebo nečlenské funkce v další jmenné prostory. V C ++ (na rozdíl od C) main()
nelze volat rekurzivně a nelze si vzít jeho adresu.
C#
Při spuštění program napsaný v jazyce C # , že CLR hledá způsob statické označeny .entrypoint
směrnicí IL, který se buď žádné argumenty, ani jediný argument typu string[]
, a má návratový typ void
nebo int
, a spustí jej.
static void Main();
static void Main(string[] args);
static int Main();
static int Main(string[] args);
Jsou předávány argumenty příkazového řádku args
, podobně jako v Javě. U verzí Main()
vrácení celého čísla, podobně jako v C i C ++, se předává zpět do prostředí jako stav ukončení procesu.
Od C # 7.1 existují další čtyři možné podpisy vstupního bodu, které umožňují asynchronní provádění v Main()
metodě.
static Task Main()
static Task<int> Main()
static Task Main(string[])
static Task<int> Main(string[])
Task
A Task<int>
typy jsou asynchronní ekvivalenty void
a int
.
Čistý
Clean je funkční programovací jazyk založený na přepisování grafů. Počáteční uzel je pojmenován Start
a má typ, *World -> *World
pokud změní svět, nebo nějaký pevný typ, pokud program vytiskne výsledek pouze po zmenšení Start
.
Start :: *World -> *World
Start world = startIO ...
Nebo ještě jednodušší
Start :: String
Start = "Hello, world!"
Jeden řekne kompilátoru, kterou možnost použít ke generování spustitelného souboru.
Společný Lisp
ANSI Common Lisp nedefinuje hlavní funkci; místo toho se kód načte a vyhodnotí shora dolů ve zdrojovém souboru. Následující kód však bude emulovat hlavní funkci.
(defun hello-main ()
(format t "Hello World!~%"))
(hello-main)
D
V D je funkční prototyp z hlavních funkčních vypadá jako jeden z následujících:
void main();
void main(string[] args);
int main();
int main(string[] args);
Argumenty příkazového řádku jsou předávány args
podobně jako v C # nebo Java. U verzí main()
vrácení celého čísla, podobně jako v C i C ++, se předává zpět do prostředí jako stav ukončení procesu.
FORTRAN
FORTRAN nemá hlavní podprogram nebo funkci. Místo toho lze PROGRAM
jako první řádek použít příkaz k určení, že programová jednotka je hlavním programem, jak je znázorněno níže. Příkaz PROGRAM
nelze použít pro rekurzivní volání.
PROGRAM HELLO
PRINT *, "Cint!"
END PROGRAM HELLO
Některé verze Fortranu, jako jsou například verze v systému IBM System / 360 a následných sálových počítačích, nepodporují příkaz PROGRAM. Mnoho překladačů od jiných výrobců softwaru umožní sestavit program Fortran bez příkazu PROGRAM. V těchto případech je za hlavní program považován jakýkoli modul, který má příkaz bez komentáře, kde nedojde k žádnému příkazu SUBROUTINE, FUNCTION nebo BLOCK DATA.
KOMÁR
Pomocí GNAT není programátor povinen psát funkci s názvem main
; zdrojový soubor obsahující jeden podprogram lze zkompilovat do spustitelného souboru. Pořadač však vytvoří balíček ada_main
, který bude obsahovat a exportovat hlavní funkci ve stylu C.
Jít
V programovacím jazyce Go začíná provádění programu main
funkcí funkcepackage main
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Neexistuje žádný způsob, jak získat přístup k argumentům nebo návratovému kódu mimo standardní knihovnu v Go. K nim lze přistupovat prostřednictvím os.Args
a os.Exit
respektive, oba jsou součástí "os"
balení.
Haskell
Program Haskell musí obsahovat název main
vázaný na hodnotu typu IO t
, pro nějaký typ t
; což je obvykle IO ()
. IO
je monad , který organizuje vedlejší účinky, pokud jde o čistě funkční kód. main
Hodnota představuje vedlejší účinky-ful výpočet postará program. Výsledek výpočtu, který představuje, main
je zahozen; to je důvod, proč main
má obvykle typ IO ()
, který udává, že typ výsledku výpočtu je ()
je typ jednotky , který neobsahuje žádné informace.
main :: IO ()
main = putStrLn "Hello, World!"
Argumenty příkazového řádku nejsou dány main
; musí být načteny pomocí jiné akce IO, například System.Environment.getArgs
.
Jáva
Programy Java se začínají spouštět u hlavní metody třídy, která má jednu z následujících záhlaví metody :
public static void main(String[] args)
public static void main(String... args)
public static void main(String args[])
Jsou předány argumenty příkazového řádku args
. Stejně jako v C a C ++ je název „ main()
“ speciální. Hlavní metody Java nevracejí hodnotu přímo, ale jednu lze předat pomocí této System.exit()
metody.
Na rozdíl od C není název programu zahrnut do args
, protože se jedná o název třídy, která obsahuje hlavní metodu, takže je již známa. Také na rozdíl od C nemusí být zahrnut počet argumentů, protože pole v Javě mají pole, které sleduje, kolik prvků existuje.
Hlavní funkce musí být součástí třídy. Je to proto, že v Javě musí být vše obsaženo ve třídě. Například ahoj světový program v Javě může vypadat takto:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
Chcete-li spustit tento program, musíte zavolat java HelloWorld
do adresáře, kde existuje kompilovaný soubor třídy HelloWorld.class
). Alternativně spustitelné soubory JAR používají soubor manifestu k určení vstupního bodu způsobem, který je z pohledu uživatele nezávislý na souborovém systému.
LOGO
Ve FMSLogu se postupy po načtení nespouštějí. K jejich provedení je nutné použít tento kód:
to procname ... ; Startup commands (such as print [Welcome]) end
make "startup [procname]
Proměnná startup
se používá pro spouštěcí seznam akcí, ale konvencí je, že to volá jiný postup, který akce spouští. Tento postup může být libovolný.
OCaml
OCaml nemá žádnou main
funkci. Programy se vyhodnocují shora dolů.
Argumenty příkazového řádku jsou k dispozici v poli s názvem Sys.argv
a stav ukončení je ve výchozím nastavení 0.
Příklad:
print_endline "Hello World"
Pascal
V Pascalu je hlavní procedura jediným nepojmenovaným blokem v programu. Protože programy Pascal definují procedury a funkce v přísnějším pořadí zdola nahoru než programy C, C ++ nebo Java, je hlavní procedura obvykle posledním blokem v programu. Pascal nemá zvláštní význam pro jméno „ main
“ nebo jiné podobné jméno.
program Hello(Output);
begin
writeln('Hello, world!');
end.
Argumenty příkazového řádku se počítají ParamCount
a jsou přístupné jako řetězce od ParamStr(n)
, s n mezi 0 a ParamCount
.
Verze Pascalu, které podporují jednotky nebo moduly, mohou také v každém obsahovat nepojmenovaný blok, který se používá k inicializaci modulu. Tyto bloky jsou provedeny před voláním hlavního vstupního bodu programu.
Perl
V Perlu není žádná hlavní funkce. Výpisy jsou prováděny shora dolů.
Argumenty příkazového řádku jsou k dispozici ve speciálním poli @ARGV
. Na rozdíl od C @ARGV
neobsahuje název programu, který je $0
.
PHP
PHP nemá „hlavní“ funkci. Počínaje prvním řádkem skriptu PHP se jakýkoli kód, který není zapouzdřený v záhlaví funkce, provede, jakmile je vidět.
Štika
V Pike je syntaxe podobná syntaxi C a C ++. Poprava začíná v main
. Proměnná " argc
" udržuje počet argumentů předaných programu. Proměnná „ argv
“ obsahuje hodnotu spojenou s argumenty předanými programu.
Příklad:
int main(int argc, array(string) argv)
Krajta
Programy v Pythonu se vyhodnocují shora dolů, jak je obvyklé ve skriptovacích jazycích: vstupním bodem je začátek zdrojového kódu. Vzhledem k tomu, že použití musí předcházet definicím, jsou programy obvykle strukturovány s definicemi nahoře a kódem, který se má provádět dole (bez indentace), podobně jako kód pro kompilátor s jedním průchodem , například v Pascalu.
Alternativně může být program strukturován s explicitní main
funkcí obsahující kód, který má být spuštěn, když je program proveden přímo, ale který může být také vyvolán importem programu jako modulu a voláním funkce. To lze provést pomocí následujícího idiomu, který se spoléhá na to, že interní proměnná __name__
je nastavena na, __main__
když je program spuštěn, ale ne když je importován jako modul (v takovém případě je místo toho nastaven na název modulu); existuje mnoho variant této struktury:
import sys
def main(argv):
n = int(argv[1])
print(n + 1)
if __name__ == '__main__':
sys.exit(main(sys.argv))
V tomto idiomu je volání pojmenovaného vstupního bodu main
explicitní a interakce s operačním systémem (přijímání argumentů, volání ukončení systému) se provádí explicitně pomocí volání knihovny, které jsou nakonec zpracovány modulem runtime Pythonu. Tento kontrast s C, kde jsou prováděny implicitně runtime, na základě konvence.
QB64
Jazyk QB64 nemá žádnou hlavní funkci, kód, který není ve funkci, nebo se nejprve provede podprogram, shora dolů:
print "Hello World! a =";
a = getInteger(1.8d): print a
function getInteger(n as double)
getInteger = int(n)
end function
Argumenty příkazového řádku (pokud existují) lze číst pomocí funkce COMMAND $:
dim shared commandline as string
commandline = COMMAND$
'Several space-separated command line arguments can be read using COMMAND$(n)
commandline1 = COMMAND$(2)
Rubín
V Ruby není žádná zřetelná hlavní funkce. Místo toho se kód zapsaný mimo jakýkoli class .. end
nebo obor module .. end
provádí v kontextu speciálního main
objektu. K tomuto objektu lze přistupovat pomocí self
:
irb(main):001:0> self
=> main
Má následující vlastnosti:
irb(main):002:0> self.class
=> Object
irb(main):003:0> self.class.ancestors
=> [Object, Kernel, BasicObject]
Metody definované mimo " class
nebo" module
rozsah jsou definovány jako soukromé metody " main
" objektu. Protože třída „ main
“ je Object
, tyto metody se stávají soukromými metodami téměř každého objektu:
irb(main):004:0> def foo
irb(main):005:1> 42
irb(main):006:1> end
=> nil
irb(main):007:0> foo
=> 42
irb(main):008:0> [].foo
NoMethodError: private method `foo' called for []:Array
from (irb):8
from /usr/bin/irb:12:in `<main>'
irb(main):009:0> false.foo
NoMethodError: private method `foo' called for false:FalseClass
from (irb):9
from /usr/bin/irb:12:in `<main>'
Počet a hodnoty argumentů příkazového řádku lze určit pomocí ARGV
konstantního pole:
$ irb /dev/tty foo bar
tty(main):001:0> ARGV
ARGV
=> ["foo", "bar"]
tty(main):002:0> ARGV.size
ARGV.size
=> 2
První prvek ARGV
, ARGV[0]
obsahuje první argument příkazového řádku, nikoli název programu vykonán, stejně jako v C je k dispozici název programu pomocí $0
nebo $PROGRAM_NAME
.
Podobně jako v Pythonu lze použít:
if __FILE__ == $PROGRAM_NAME
# Put "main" code here
end
provést nějaký kód, pouze pokud byl jeho soubor uveden ve ruby
vyvolání.
Rez
V Rustu je vstupním bodem programu funkce s názvem main
. Tato funkce se obvykle nachází v souboru s názvem main.rs
nebo lib.rs
.
// In `main.rs`
fn main() {
println!("Hello, World!");
}
Od verze Rust 1.26.0 může navíc hlavní funkce vracet Result
:
fn main() -> Result<(), std::io::Error> {
println!("Hello, World!");
Ok(()) // Return a type `Result` of value `Ok` with the content `()`, i.e. an empty tuple.
}
Rychlý
Při spuštění na hřišti Xcode se Swift chová jako skriptovací jazyk a provádí příkazy shora dolů; kód nejvyšší úrovně je povolen.
// HelloWorld.playground
let hello = "hello"
let world = "world"
let helloWorld = hello + " " + world
print(helloWorld) // hello world
Kakao - a kakao dotykový založené aplikace napsané v Swift jsou obvykle inicializuje se @NSApplicationMain
a @UIApplicationMain
atributy, resp. Tyto atributy jsou z hlediska účelu rovnocenné se main.m
souborem v projektech Objective-C : implicitně deklarují main
funkci, která volá, UIApplicationMain(_:_:_:_:)
která vytváří instanci UIApplication
. Následující kód je výchozí způsob, jak inicializovat aplikaci pro iOS založenou na Cocoa Touch a deklarovat jejího delegáta aplikace.
// AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
}
Visual Basic
V jazyce Visual Basic , pokud projekt neobsahuje žádné formuláře, může být spouštěcím objektem Main()
postup. Command$
Funkce může být volitelně použit pro přístup k argumentu část příkazového řádku použitého ke spuštění programu:
Sub Main()
Debug.Print "Hello World!"
MsgBox "Arguments if any are: " & Command$
End Sub
Xojo
V Xojo existují dva různé typy projektů, každý s jiným hlavním vstupním bodem. Desktopové (GUI) aplikace začínají App.Open
událostí Application
objektu projektu . Konzolové aplikace začínají App.Run
událostí ConsoleApplication
objektu projektu . V obou případech se hlavní funkce generuje automaticky a nelze ji z projektu odebrat.
Viz také
- crt0 , sada spouštěcích rutin spuštění spojených s programem C.
- Runtime systém
Reference
externí odkazy
- Ahoj ze světa bez libc! (Část 1) , 16. března 2010
- Jak hlavní metoda funguje v Javě