Vstupní bod - Entry point

Příklad hlavní funkce v C #.
Jak by to mohlo vypadat ve zdrojovém kódu C # . Různé části jsou označeny pro referenci.Main()

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_entrypoli hlavičky ELF. V GNU Compiler Collection (gcc) je vstupním bodem použitým linkerem _startsymbol. Podobně ve formátu Portable Executable , který se používá v systému Microsoft Windows , je vstupní bod určen AddressOfEntryPointpolem, 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í mainfunkce. 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 atexitobsluž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 mainfunkcí 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 argca argvmůž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 getenvv 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 argcje nezáporné a to argv[argc]je nulový ukazatel . Podle konvence jsou argumenty příkazového řádku specifikovány argca argvzahrnují název programu jako prvního prvku, pokud argcje větší než 0; pokud uživatel zadá příkaz „ rm file“, prostředí inicializuje rmproces pomocí argc = 2a argv = {"rm", "file", NULL}. Stejně argv[0]jako název, pod kterým se procesy objevují ps, topatd., 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 execsysté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 staticnebo 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 .entrypointsměrnicí IL, který se buď žádné argumenty, ani jediný argument typu string[], a má návratový typ voidnebo 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[])

TaskA Task<int>typy jsou asynchronní ekvivalenty voida int.

Čistý

Clean je funkční programovací jazyk založený na přepisování grafů. Počáteční uzel je pojmenován Starta má typ, *World -> *Worldpokud 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 argspodobně 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 PROGRAMjako 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 PROGRAMnelze 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 mainfunkcí 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.Argsa os.Exitrespektive, oba jsou součástí "os"balení.

Haskell

Program Haskell musí obsahovat název mainvázaný na hodnotu typu IO t, pro nějaký typ t; což je obvykle IO (). IOje monad , který organizuje vedlejší účinky, pokud jde o čistě funkční kód. mainHodnota představuje vedlejší účinky-ful výpočet postará program. Výsledek výpočtu, který představuje, mainje zahozen; to je důvod, proč mainmá 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 HelloWorlddo 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.

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á startupse 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 mainfunkci. Programy se vyhodnocují shora dolů.

Argumenty příkazového řádku jsou k dispozici v poli s názvem Sys.argva 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í ParamCounta 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 @ARGVneobsahuje 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í mainfunkcí 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 mainexplicitní 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 .. endnebo obor module .. endprovádí v kontextu speciálního mainobjektu. 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 " classnebo" modulerozsah 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í ARGVkonstantní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í $0nebo $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 rubyvyvolá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.rsnebo 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 @NSApplicationMaina @UIApplicationMainatributy, resp. Tyto atributy jsou z hlediska účelu rovnocenné se main.msouborem v projektech Objective-C : implicitně deklarují mainfunkci, 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.Openudálostí Applicationobjektu projektu . Konzolové aplikace začínají App.Runudálostí ConsoleApplicationobjektu projektu . V obou případech se hlavní funkce generuje automaticky a nelze ji z projektu odebrat.

Viz také

Reference

externí odkazy