Bartels :: Bartels AutoEngineer :: BAE Dokumentation :: User Language Programmierhandbuch :: Sprachbeschreibung :: Datentypen und Definitionen |
Bartels User Language - Programmierhandbuch2.3 Datentypen und Definitionen |
Die Bartels User Language stellt die folgenden elementaren Datentypen zur Verfügung:
char | Zeichen aus dem Zeichensatz der Maschine |
int | ganzzahliger numerischer Wert |
double | doppelt genauer numerischer Gleitkommawert |
string | Zeichenkette (char -Vektor) |
index | Index auf definierte DDB-Struktur des Bartels AutoEngineer |
Daneben ist die Verwendung folgender zusammengesetzter Datentypen möglich:
Vektor | Zusammenfassung von Elementen gleichen Datentyps |
struct | Zusammenfassung von Elementen unterschiedlichen Datentyps |
Verschiedene Operatoren können implizite Datentypumwandlungen verursachen. So setzen eine Reihe arithmetischer Operationen definierte Datentypen bzw. Datentyppaare für ihre Operanden voraus. Ebenso wird bei der Zuweisung eines Wertes an eine Variable oder der Übergabe von Funktionsparametern eine entsprechende Datentypkompatibilität verlangt. Sofern an irgendeiner Stelle im Programm die geforderte Kompatibilität nicht vorliegt, wird versucht, den Wert des betroffenen Operanden in den gewünschten Datentyp zu überführen (man spricht von einem "type cast"). Diese Typkonvertierung läuft nach folgenden Regeln ab: Zulässige Umwandlungen ohne Informationsverlust sind
char
in
int
oder
char
in
string
, sowie
int
in
double
; ebenfalls zulässige Umwandlungen - jedoch mit möglichem Informationsverlust - sind
int
in
char
, sowie
double
in
int
. Der Compiler gibt Fehlermeldungen aus, wenn auch unter Ausnutzung der Typkonvertierungsregeln keine Typkompatibilität erreicht werden kann.
Alle globalen und lokalen Variablen müssen vor ihrem Gebrauch deklariert werden, damit sowohl ihr Datentyp als auch ihr Name definiert sind. Durch derartige Vereinbarungen wird festgelegt, wie einzelne, vom Benutzer eingeführte Namen durch die User Language zu interpretieren sind. Jede Vereinbarung besteht aus einer Datentypspezifikation sowie einer Liste von Deklaratoren; die Deklaratoren wiederum bestehen aus dem Variablennamen sowie wahlweise einer Initialisierung der Variablen.
Beispiel für die Deklaration von
char
-Variablen:
char c; char TAB = '\t', NEWLINE = '\n';
In obigem Beispiel werden die
char
-Variablen
c
(nicht initialisiert) sowie
TAB
und
NEWLINE
(initialisiert mit dem Tabulator- bzw. dem Zeilenvorschub-Zeichen) deklariert.
Beispiel für die Deklaration von
int
-Variablen:
int i, MAXLINELEN = 80; int pincount = 0;
In obigem Beispiel werden die
int
-Variablen
i
(nicht initialisiert) und
MAXLINELEN
(initialisiert mit dem Wert 80), sowie
pincount
(initialisiert mit 0) vereinbart.
Beispiel für die Deklaration von
double
-Variablen:
double x_coord, y_coord; double MMTOINCH = 1.0/25.4; double starttime = clock();
In obigem Beispiel werden die
double
-Variablen
x_coord
und
y_coord
(nicht initialisiert),
MMTOINCH
(initialisiert mit einem numerischen Ausdruck), sowie
starttime
deklariert; die Variable
starttime
wird initialisiert mit dem Resultatwert der (System-)Funktion
clock, welche die Prozessor-Zeit zurückgibt.
Beispiel für die Deklaration von
string
-Variablen:
string s1; string ProgName = "TESTPROGRAM", ProgVer = "V1.0"; string ProgHeader = ProgName+"\t"+ProgVer;
In obigem Beispiel werden die
string
-Variablen
s1
(nicht initialisiert),
ProgName
und
ProgVer
(initialisiert mit
TESTPROGRAM
und
V1.0
), sowie
ProgHeader
deklariert;
ProgHeader
wird dabei mit einem Ausdruck initialisiert, der sich durch Aneinanderfügen der
string
-Variablen
ProgName
, des Tabulatorzeichens, sowie der
string
-Variablen
ProgVer
ergibt.
Beispiel für die Deklaration von
index
-Variablen:
index L_MACRO macro; index L_CNET net1, net2;
In obigem Beispiel werden die
index
-Variablen
macro
(vom
index
-Variablentyp
L_MACRO) sowie
net1
und
net2
(vom
index
-Variablentyp
L_CNET) vereinbart. Bei der Deklaration von
index
-Variablen besteht die Spezifikation des Datentyps aus dem Schlüsselwort
index
und zusätzlich dem Namen des
index
-Variablentyps (hier
L_MACRO bzw.
L_CNET). Die Namen für die
index
-Variablentypen sind vordefiniert (siehe
Anhang B).
Es muss sichergestellt sein, dass in einem Programm nur zueinander kompatible
index
-Variablentypen verwendet werden. Dies beruht auf der Tatsache, dass über
index
-Datentypen der Zugriff auf entsprechende Einträge aus der Design-Datenbank (DDB) des
Bartels AutoEngineer definiert wird; die Verfügbarkeit dieser
DDB-Einträge unterscheidet sich je nach Interpreterumgebung (im
Schaltplaneditor sind andere Datentypen definiert als im Layout). Bei der Verwendung zueinander nicht kompatibler
index
-Variablentypen im selben Programm gibt der
User Language Compiler eine entsprechende Fehlermeldung aus und erzeugt keinen Code. Ähnlich verhält sich der
User Language Interpreter; beim Versuch ein
User Language-Programm aufzurufen, das zur Interpreterumgebung inkompatible
index
-Datentyp-Referenzen enthält, gibt das System eine entsprechende Fehlermeldung aus und führt das betreffende Programm nicht aus. Die Information über die Kompatibilität der
index
-Datentypen ist dem
Anhang A bzw. dem
Anhang B zu entnehmen.
Unter einem Vektor, auch bezeichnet als Feld oder Array, versteht man die Zusammenfassung einzelner Elemente gleichen Datentyps. Bei der Deklaration von Vektorvariablen wird neben der Spezifikation des Datentyps und der Definition des Variablennamens zusätzlich die Angabe der Vektordimension benötigt. Diese Dimensions-Angabe erfolgt durch Anfügen eckiger Klammern an den Variablennamen, wobei jeweils ein Klammernpaar einer Dimension entspricht. Bei der Initialisierung von Vektor-Elementen sind die Initialisierungswerte durch Kommata zu trennen, und jede Vektordimension ist in geschweifte Klammern einzuschließen.
Beispiel für die Deklaration von Vektor-Variablen:
int intary[], intfield[][][]; double valtab[][] = { { 1.0, 2.54, 3.14 }, { 1.0/valtab[0][1], clock() } }; string TECHNOLOGIES[] = { "TTL", "AC", "ACT", "ALS", "AS", "F", "H", "HC", "HCT", "HCU", "L", "LS", "S" };
Obiges Beispiel enthält die Deklarationen der
int
-Vektoren
intary
und
intfield
(ein- bzw. dreidimensional), des zweidimensionalen
double
-Vektors
valtab
, sowie des eindimensionalen
string
-Vektors
TECHNOLOGIES
. In den Deklarationen für
valtab
und
TECHNOLOGIES
sind Initialisierungen angegeben, die den folgenden Zuweisungen entsprechen:
valtab[0][0] = 1.0; valtab[0][1] = 2.54; valtab[0][2] = 3.14; valtab[1][0] = 1.0/valtab[0][1]; valtab[1][1] = clock(); TECHNOLOGIES[0] = "TTL"; TECHNOLOGIES[1] = "AC"; TECHNOLOGIES[2] = "ACT"; : TECHNOLOGIES[11] = "LS"; TECHNOLOGIES[12] = "S";
Es sei an dieser Stelle nochmals darauf hingewiesen, dass in der
User Language der elementare Datentyp
string
einem eindimensionalen
char
-Vektor entspricht. Die Deklarationen
string s;
und
char s[];
sind also äquivalent.
Unter einer Struktur versteht man die Zusammenfassung mehrerer, jeweils durch Name und Datentyp definierter Elemente, die in einem bestimmten verarbeitungstechnischen oder auch nur logischen Zusammenhang stehen. Bei der Vereinbarung von Strukturen unterscheidet man die Strukturdefinition und die Strukturdeklaration. Die Strukturdefinition besteht aus dem Schlüsselwort
struct
, dem Namen der Strukturdefinition, und - in geschweiften Klammern - den Definitionen der Strukturelemente. Die Strukturdeklaration besteht aus dem Schlüsselwort
struct
, dem Namen einer gültigen Strukturdefinition, sowie dem Namen der Variablen, die der Strukturdefinition zugeordnet wird. Strukturdefinition und Strukturdeklaration können zusammengefasst werden, wobei dann auch der Name für die Strukturdefinition entfallen kann. Initialisierungen innerhalb von Strukturdeklarationen sind in der aus den Vektordeklarationen bekannten Nomenklatur zulässig.
Beispiel für die Vereinbarung von Strukturen:
// Structure declarations struct coordpair { double x double y; }; struct coordpair elementsize = { bae_planwsux()-bae_planwslx(), bae_planwsuy()-bae_planwsly() }; struct elementdes { string fname, ename; int class; struct coordpair origin, size; } element = { bae_planfname(), bae_planename(), bae_planddbclass(), { bae_planwsnx(), bae_planwsny() }, elementsize }; struct { string id, version; struct { int day; string month; int year; } reldate; } program = { "UL PROGRAM", "Version 1.1", { 4, "July", 1992 } };
Obiges Beispiel enthält die Definition der Struktur
coordpair
, die Deklaration der Variablen
elementsize
(Struktur vom Typ
coordpair
), die Definition der Struktur
elementdes
, die Deklaration der Variablen
element
(Struktur vom Typ
elementdes
), sowie die Deklaration der Strukturvariablen
program
. Die in den Deklarationen für
elementsize
,
element
und
program
enthaltenen Initialisierungen entsprechen den folgenden Zuweisungen:
elementsize.x=bae_planwsux()-bae_planwslx(); elementsize.y=bae_planwsuy()-bae_planwsly(); element.fname=bae_planfname(); element.ename=bae_planename(); element.class=bae_planddbclass(); element.origin.x=bae_planwsnx(); element.origin.y=bae_planwsny(); element.size=plansize; program.id="UL PROG"; program.version="Version 1.1"; program.reldate.day=4; program.reldate.month="July"; program.reldate.year=1992;
Auch die Definition von Vektoren aus Strukturen bzw. die Verwendung von Vektordatentypen innerhalb von Strukturen ist möglich, wie das folgende Beispiel demonstriert:
struct drilldef { index L_DRILL drilltool; struct { double x, y; } drillcoords[]; } drilltable[];
Bartels User Language verfügt über einen Mechanismus zur Umbenennung von Datentypen. Dabei handelt es sich nicht um die Schaffung eines neuen Datentyps, sondern lediglich um die Vergabe eines zusätzlichen Namens für einen bereits bekannten Typ. Eine derartige Typumbennung erfolgt durch die Angabe des Schlüsselwortes
typedef
gefolgt von der Spezifikation des Datentyps sowie dem zur Bezeichnung dieses Datentyps zusätzlich einzuführenden Namen. Ein mit
typedef
eingeführter Name kann anschließend zur Typspezifikation bei der Deklaration von Variablen, Funktionen und Funktionsparametern verwendet werden.
Beispiel für Typ-Umbennungen:
typedef index L_CNET NETLIST[]; typedef int IARY[]; typedef IARY MAT_2[]; typedef struct { int pointcount; struct { int t; double x,y; } pointlist[]; } POLYLIST[]; MAT_2 routmatrix; NETLIST netlist; POLYLIST polygonlist;
In obigem Beispiel werden die drei Variablen
routmatrix
(zweidimensionaler int
-Vektor),
netlist
(eindimensionaler index
-Vektor vom Typ
L_CNET), sowie
polygonlist
(eindimensionaler Vektor aus Strukturen, die ihrerseits ein
int
-Element und einen
struct
-Vektor enthalten) deklariert.
Bei komplexen Operationen und Berechnungen ist es meist nicht notwendig, zu wissen, wie das Ergebnis zustande kommt; interessant ist lediglich das Ergebnis selbst. Auch ist es wünschenswert, bestimmte Bearbeitungsfolgen immer wieder verwenden zu können. Mit Hilfe von Funktionen ist die Zerlegung großer Problemstellungen in kleinere, d.h. die Modularisierung und Vereinfachung von Programmen möglich. In der Bartels User Language wird unterschieden zwischen den Systemfunktionen und den durch den Anwender definierten Funktionen.
Die Definitionen der Systemfunktionen sind dem Compiler bekannt, die Funktionen selbst sind in den Interpreter eingebunden. Anhang C enthält die Beschreibung dieser Systemfunktionen. Der Anwender kann also bei der Implementierung seiner Programme die Systemfunktionen verwenden und hat darüber hinaus die Möglichkeit, eigene Funktionen zu definieren.
Eine Funktionsdefinition besteht aus dem Funktionskopf (Header) und dem Funktionsrumpf (Block). Der Header enthält eine Typspezifikation und den Namen der Funktion, sowie die Definition und Deklaration der Funktionsparameter. Die Typspezifikation definiert den Datentyp des Wertes, den die Funktion an den Aufrufer zurückliefert (Rückgabewert). Hierbei steht zusätzlich der Datentyp
void
zur Verfügung, der dem Compiler angibt, dass die Funktion keinen Rückgabewert liefert. Wird die Datentypspezifikation weggelassen, dann wird der Funktion automatisch der Datentyp
int
zugeordnet. Nach dem Funktionsnamen folgt die Parameterdefinition. Diese besteht aus einer in runde Klammern eingeschlossenen Liste von durch Kommata getrennten Parameternamen bzw. Parameterdeklarationen. Für den Fall, dass die Funktion gar keine Parameter enthält, ist lediglich das Klammernpaar anzugeben. Alle definierten Parameter (außer den bereits in der Liste der Parameterdefinitionen deklarierten sowie den
int
-Typen) müssen nach der Liste der Parameterdefinitionen explizit vereinbart werden. Diese Parameterdeklarationen sind wie Variablendeklarationen vorzunehmen. Nach dem Funktionskopf muss der Funktionsrumpf definiert werden. Dieser ist ein durch geschweifte Klammern umschlossener Block von Anweisungen.
Beispiele für Funktionsdefinitionen:
double netroutwidth(index L_CNET net) // Get the routing width of a given net // Returns : width or 0.0 if two pins with different width { index L_CPIN pin; // Pin index int pincnt=0; // Pin count double rw=0.0; // Rout width // Loop thru all pins forall (pin of net) { // Test if the pin introduces a new rout width if (pin.RWIDTH!=rw && pincnt++>0) return(0.0); // Set the rout width rw=pin.RWIDTH; } // Return the rout width return(rw); } int allpartsplaced() // Test if all netlist-defined parts are placed // Returns : 1 if all parts are placed or zero otherwise { index L_CPART cpart; // Connection part index // Loop thru the connection part list forall (cpart where !cpart.USED) // Unplaced part matched return(0); // All parts are placed return(1); } double getdistance(xs,ys,xe,ye) // Get the distance between two points // Returns : the distance length value double xs, ys; // Start point coordinate double xe, ye; // End point coordinate { double xd=xe-xs; // X distance double yd=ye-ys; // Y distance // Calculate and return the distance (Pythagoras) return(sqrt(xd*xd+yd*yd)); } double arclength(r,a1,a2) // Get arc segment length by radius and start-/end-point angle // Returns : the arc segment length value double r; // Radius double a1; // Start point angle (in radians) double a2; // End point angle (in radians) { // Arc; "absolute" angle between start and end point double arc = a1<a2 ? a2-a1 : 2*PI()+a2-a1; // Get and return the arc segment length return(arc*r); } double getangle(cx,cy,x,y) // Get the angle of a circle arc point // Returns : the angle (in radians; range [0,2*PI]) double cx, cy; // Circle center coordinate double x, y; // Circle arc point coordinate { double res; // Result value // Get arc tangent of angle defined by circle point res=atan2(y-cy,x-cx); // Test the result if (res<0.0) // Get the "absolute" angle value res=PI()-res; // Return the result value return(res); } double PI() // Returns the value of PI in radians { // Convert 180 degree and return the result return(cvtangle(180.0,1,2)); } void cputimeuse(rn,st) // Report CPU time usage (in seconds) string rn; // Routine name double st; // Start time { // Print CPU time elapsed since start time printf("(%s) Elapsed CPU Time = %6.1f [Sec]\n",rn,clock()-st); }
Jede in einem User Language-Programm (bzw. Programmtext) per Definition bekannte Funktion kann innerhalb dieses Programmes (bzw. in dem entsprechenden Programm-Modul) auch aufgerufen werden. Bei der Verwendung von User Language Systemfunktionen besteht jedoch die Einschränkung, dass in einem Programm nur zueinander kompatible Systemfunktionen verwendet werden können. Dies beruht auf der Tatsache, dass über derartige Funktionsaufrufe ggf. Aktionen ausgelöst werden, die nur in einer bestimmten Interpreterumgebung ausgeführt werden können (die Funktion zur Festlegung von Plotparametern im CAM-Prozessor des AutoEngineers kann selbstverständlich nicht im Schaltplaneditor aufgerufen werden). Bei der Verwendung zueinander nicht kompatibler Systemfunktionen gibt der User Language Compiler eine Fehlermeldung aus und erzeugt keinen Programm-Code. Ähnlich verhält sich der User Language Interpreter; beim Versuch ein User Language-Programm aufzurufen, das zur Interpreterumgebung inkompatible Systemfunktions-Referenzen enthält, erzeugt das System eine entsprechende Fehlermeldung und führt das betreffende Programm nicht aus. Die Information über die Kompatibilität der User Language-Systemfunktionen ist dem Anhang A bzw. dem Anhang C zu entnehmen.
Der Funktionsaufruf setzt sich zusammen aus dem Funktionsnamen und der in runden Klammern eingeschlossenen Liste der aktuellen Parameter, die der Funktion übergeben werden soll.
Die Inhalte der global definierten Variablen eines Programms stehen grundsätzlich in jeder Funktion desselben Geltungsbereichs zur Verfügung, d.h. globale Variablen können zur Übergabe von Werten an Funktionen benutzt werden. Darüber hinaus besteht die Möglichkeit der Wertübergabe über Funktionsparameter. Die Übergabe per Parameter kann einfach kontrolliert werden und ist daher i.d.R. der Methode der Übergabe über globale Variablen vorzuziehen. Die Liste der aktuellen Parameter, also der Ausdrücke, die man bei einem Funktionsaufruf übergibt, muss mit der formalen Parameterdefinition (also Anzahl und Datentypen) der aufzurufenden Funktion übereinstimmen. Beim Funktionsaufruf werden die Werte der aktuellen Parameter in die entsprechenden formalen Parameter kopiert. Nach erfolgreicher Beendigung der Funktion wird jeder durch die Funktion geänderte Parameterwert wieder auf den aktuellen Parameter zurückgespeichert, sofern dieser eine Variablenreferenz darstellt. Schließlich besteht noch die Möglichkeit der Wertübergabe über den Rückgabewert der Funktion. Dabei wird innerhalb der Funktion mit Hilfe der
return
-Anweisung ein Funktionsergebnis gesetzt, das anschließend vom Aufrufer innerhalb des Ausdrucks, der den Funktionsaufruf enthält, ausgewertet werden kann.
Beispiel für Funktionsaufruf und Wertübergabe:
// Date structure struct date { int day, month, year; }; // Global program variables string globalstr="Global string"; int fctcallcount=0; // Main program main() { // Local variables of main string resultstr="function not yet called"; struct date today = { 0, 0, 0 }; double p=0.0, b=2.0, e=10.0; // Print the global variables printf("fctcallcount=%d, %s\n",fctcallcount,globalstr); // Print the local variables printf("resultstr=\"%s\"\n",resultstr); printf("today : %d,%d,%d",today.day,today.month,today.year); printf("\t\tb=%.1f, e=%.1f, p=%.1f\n",b,e,p); // Call function resultstr=function(today,b,e,p); // Print the global variables printf("fctcallcount=%d, %s\n",fctcallcount,globalstr); // Print the local variables printf("resultstr=\"%s\"\n",resultstr); printf("today : %d,%d,%d",today.day,today.month,today.year); printf("\t\tb=%.1f, e=%.1f, p=%.1f\n",b,e,p); } string function(curdate,base,exponent,power) struct date curdate; // Current date parameter double base; // Base parameter double exponent; // Exponent parameter double power; // Power parameter { // Increment the function call count fctcallcount++; // Set the global string globalstr="Global string changed by function"; // Get the current date get_date(curdate.day,curdate.month,curdate.year); // Calculate the power power=pow(base,exponent); // Return with a result string return("function result string"); }
Obiges Beispiel-Programm erzeugt folgende Ausgabe:
fctcallcount=0, Global string resultstr="function not yet called" today : 0,0,0 b=2.0, e=10.0, p=0.0 fctcallcount=1, Global string changed by function resultstr="function result string" today : 4,6,92 b=2.0, e=10.0, p=1024.0
Jede Funktion der
User Language behält nach ihrem Aufruf solange die Kontrolle, bis sie auf einen weiteren Funktionsaufruf, auf eine
return
-Anweisung, oder nach der Abarbeitung der letzten Anweisung der Funktion auf das Funktionsende trifft. Bei einem Funktionsaufruf wird die Kontrolle an die aufgerufene Funktion weitergegeben. Beim Erreichen einer
return
-Anweisung oder am Funktionsende wird die Kontrolle an den Aufrufer der Funktion zurückgegeben. Ist in einem Programm eine Anwenderfunktion mit dem Namen
main
definiert, dann erzeugt der
User Language Compiler Programm-Code, der dafür sorgt, dass - unmittelbar nach der Initialisierung der globalen Variablen - diese Funktion aufgerufen wird. Der Kontrollfluss eines
User Language-Programms beginnt also üblicherweise bei der Funktion
main
. Da bei rekursionsfreier Programmierung jede Funktion irgendwann ihre Kontrolle wieder an den Aufrufer zurückgibt, fällt die Kontrolle schließlich wieder an die
main
-Funktion. Wird darin dann das Funktionsende oder eine
return
-Anweisung erreicht, dann ist auch das Programmende erreicht, und der
User Language Interpreter kann den Kontrollfluss beenden.
Funktionen dürfen rekursiv benutzt werden, d.h. eine Funktion darf sich direkt oder indirekt selbst aufrufen. Dies ist jedoch nur dann sinnvoll, wenn sich bei jedem Aufruf ein Zustand derart verändert, dass sich irgendwann ein eindeutig definierter Endzustand einstellt, mit dessen Hilfe sich die Rekursion abbrechen lässt.
Durch die rekursive Programmierung von Funktionen kann man im Allgemeinen Programm-Code einsparen und eventuell die Lesbarkeit erhöhen. Die Programmlaufzeit und der Speicherplatzbedarf hingegen werden sich durch Rekursionen erhöhen. Daher sollte man jeweils prüfen, ob die Verwendung einer Rekursion tatsächlich nützlich ist. Auch besteht die Gefahr, dass man "versehentlich" eine Endlosrekursion implementiert, d.h. eine Rekursion, die nie den Endzustand erreicht. Der User Language Interpreter wird bei der Abarbeitung einer solchen Endlosrekursion irgendwann einen Speicher- bzw. Stapel-Überlauf feststellen, da für jeden Funktionsaufruf zumindest eine Rücksprung-Adresse gespeichert werden muss.
Bei der Referenzierung der Objekte eines User Language-Programms muss der Compiler jeweils die Gültigkeit der Referenz überprüfen. Hierzu ist jedem Objekt ein bestimmter Geltungsbereich innerhalb des Programms zugeordnet. Innerhalb dieses Geltungsbereiches ist das entsprechende Objekt bekannt und kann referenziert werden. Es wird unterschieden zwischen globalem und lokalem Geltungsbereich. Der globale Geltungsbereich erstreckt sich über das gesamte Programm (also auch auf noch einzubindende, getrennt kompilierte Programmteile bzw. Libraries), während die lokalen Geltungsbereiche des Programms Bezug nehmen auf die Funktionsdefinitionen.
Die Funktionen eines Programms sind global, d.h. im gesamten Programm gültig. Variablen- und Typ-Definitionen, die in einer Funktion vorgenommen werden, gelten nur lokal innerhalb dieser Funktion; außerhalb von Funktionen gelten derartige Definitionen als global. Die Parameterdefinitionen einer Funktione werden wie lokale Variablen behandelt und gelten daher immer nur lokal innerhalb der betreffenden Funktion. Strukturdefinitionen gelten allgemein als global im aktuell zu übersetzenden Programmtext. Durch die Zuweisung der Speicherklasse
static
kann der Geltungsbereich von Funktionen und globalen Variablen eingeschränkt werden auf den aktuell zu übersetzenden Programmtext. Die Speicherklasse
static
dient insbesondere der Vermeidung von Namenskonflikten beim Binden bzw. Linken unterschiedlicher Programm-Module bzw. Libraries.
Um Namenskonflikte zu vermeiden, müssen die Elemente jeder Objektklasse innerhalb ihres Geltungsbereichs jeweils unterschiedliche Namen besitzen. Bei der Referenzierung haben die lokalen Objekte Vorrang vor den globalen.
Bartels :: Bartels AutoEngineer :: BAE Dokumentation :: User Language Programmierhandbuch :: Sprachbeschreibung :: Datentypen und Definitionen |
Datentypen und Definitionen
© 1985-2024 Oliver Bartels F+E