Forum: Compiler & IDEs Stringlänge mit Präprozessor-Direktive bestimmen


von Thomas F. (thomas-hn) Benutzerseite


Lesenswert?

Hallo,

gibt es beim GCC eine Möglichkeit, mit einer Präprozessor-Direktive die 
Stringlänge von einem mit #define definierten String zu bestimmen?

Also z.B.:

#define TESTSTRING "Dies ist der String"

und nun mit einer Präprozessor-Direktive die Länge von 19 Zeichen 
auslesen, so dass ich diese als festen Wert in dem C-Code verwenden 
kann.

Danke,

Thomas

von Peter D. (peda)


Lesenswert?

Ein #define macht garnicht, erzeugt keinen Code und belegt keinen SRAM.

Erst da, wo man es aufruft, passiert was.

Z.B. wenn man damit eine konstante Variable anlegt, kann man mit 
sizeof() deren Länge bestimmen (abschließende 0 zählt mit).


Peter

von Hans-jürgen H. (hjherbert) Benutzerseite


Lesenswert?

Nicht im Präprozessor, aber im Compiler ist strlen() fest eingebaut und 
wird optimiert:

i = strlen( TESTSTRING ) ;
printf("Hello C-World.[%u] \n", i);

wird zu


  bc:  83 e1         ldi  r24, 0x13  ; 19
  be:  90 e0         ldi  r25, 0x00  ; 0
  c0:  9f 93         push  r25
  c2:  8f 93         push  r24
....

von Thomas F. (thomas-hn) Benutzerseite


Lesenswert?

@Hans-jürgen Herbert: Das ist genau das was gefehlt hat ;-)

Nun ist das Problem behoben.

Danke nochmals,

Thomas

von Rolf Magnus (Gast)


Lesenswert?

Ansonsten würde auch gehen:

#define TESTSTRING_LENGTH (sizeof(TESTSTRING)-1)


von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

strlen() ist natürlich nur dann dem Compiler bekannt, wenn man

. Optimierungen aktiviert hat
. ihn im hosted mode (-fhosted) betreibt

Tja, da hammer das Dilemma wieder: eigentlich wäre ein Microcontroller
so'n schönes Paradebeispiel für eine freestanding application
(-ffreestanding), aber so richtig freestanding isses eben doch nicht
mehr, sowie man Teile der C-Standard-Bibliothek verwenden möchte.
Daher auch mein Argument, doch lieber in Kauf zu nehmen, dass man
sein main() mit dem Rückkehrtyp int deklariert, statt auf derartige
Vorteile zu verzichten (für eine hosted application gibt's zwei
genau vorgeschriebene Möglichkeiten, wie main() definiert werden
darf, bei freestanding verliert main() jegliche Sonderbedeutung gemäß
Standard).

von (Gast) == (Gast)


Lesenswert?

Hallo,

wo kann man mehr über

Was_ist_das_überhaupt/Zweck/Anwendungsbeispiel/Arbeitsweise

von hosted mode und freestanding nachlesen? Bisher nutze ich mehr oder 
weniger Standard-makefiles und kümmer mich zu wenig bzw. weiß zu wenig 
um die Möglichkeiten der Build-Beeinflußung.

Danke,

von Rolf Magnus (Gast)


Lesenswert?

> für eine hosted application gibt's zwei genau vorgeschriebene
> Möglichkeiten, wie main() definiert werden darf

Da irrst du. Aus ISO/IEC9899:1999:
1
The function called at program startup is named main. The implementation
2
declares no prototype for this function. It shall be defined with a return
3
type of int and with no parameters:
4
          int main(void) { /* ... */ }
5
6
or with two parameters (referred to here as argc and argv, though any
7
names may be used, as they are local to the function in which they are
8
declared):
9
          int main(int argc, char *argv[]) { /* ... */ }
10
11
or equivalent or in some other implementation-defined manner.

Der Compiler muß also die beiden genannten Varianten akzeptieren, darf 
aber auch beliebige andere unterstützen. Es ist nur festgelegt, daß die 
Name 'main' ist.

von Stefan (Gast)


Lesenswert?

Das sehe ich anders. Es dreht sich um die Bedeutung von "shall" in "It 
shall be defined with a return type of int ..."

http://www.bartleby.com/61/37/S0313700.html schreibt dazu u.a. 
"Americans use shall to express an explicit obligation,..."

d.h. es besteht eine Verpflichtung eine der beiden Varianten zu 
benutzen.

von Rolf Magnus (Gast)


Lesenswert?

Ich sehe es als:

"It shall be defined A or B or C."

A = "with a return type of int and with no parameters"

B = "with two parameters..."

C = "in some other implementation-defined manner"

Ich sehe keinen Zwang, daß der Rückgabetyp 'int' auch für C gelten muß. 
Es könnte allerdings an einer mißverständlichen Formulierung liegen.

von Rolf Magnus (Gast)


Lesenswert?

Ach ja, was ich vergessen habe: Die Bedeutung von 'shall' innerhalb der 
C-Norm selbst ist explizit definiert und entspricht natürlich dem, was 
du geschrieben hast.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ja, die Formulierung ist recht verwaschen.  Ich denke, die zielt
darauf ab, dass man die historische Unix-Implementierung
1
int main(int argc, char **argv, char **environ);

nicht komplett verbieten wollte.  Müsste mal im rationale nachgucken
gehen.  Jetzt geh' ich aber erstmal Mittag essen. ;-)

von Stefan (Gast)


Lesenswert?

Da sag mal einer Englisch ist eine eher einfache Sprache!

"It shall be defined with a return type of int (A) and with no parameters 
(B) or with two parameters (C) or equivalent (D) or in some other 
implementation-defined manner (E)."

Variante #1: A+B
Variante #2: A+C
...

Ich muss bekennen, dass die Varianten mit D und E über meinen Horizont 
gehen. Gibt es eine offizielle Übersetzung von ISO/IEC9899:1999? Müsste 
eigentlich, oder? Nee, anscheinend nicht.
http://www.iso.org/iso/en/CatalogueDetailPage.CatalogueDetail?CSNUMBER=29237

Zu D gibt es in "meiner" Version (*) eine Fußnote 9)
"9) Thus, int can be replaced by a typedef name defined as int, or the 
type of argv can be written as char ** argv,and so on."

Daraus und daraus dass in "meiner" Version hinter dem "equivalent" noch 
ein Semikolon steht, sehe ich den D Fall als Spezialfall von A+C an

(*) WG14/N1124  Committee Draft — May 6, 2005 ISO/IEC 9899:TC2

von Rolf Magnus (Gast)


Lesenswert?

> Daraus und daraus dass in "meiner" Version hinter dem "equivalent" noch
> ein Semikolon steht, sehe ich den D Fall als Spezialfall von A+C an

Bzw. auch als Spezialfall von A+B. Ich habe die Fußnote nur weggelassen, 
weil ich sie nicht als so wichtig angesehen hatte. Es geht hier einfach 
nur darum, daß halt nicht exakt die dort angegebenen Zeilen dastehen 
müssen, sondern alles, was im Prinzip dasselbe ist, also auch:
1
typedef int frobooz;
2
#define fubar void
3
4
frobozz main(fubar);
5
{
6
}

oder:
1
typedef int  foo;
2
typedef char* bar;
3
#define blah main(
4
#define blub foo argc,
5
#define boing bar* argv)
6
7
foo blah blub boing
8
{
9
}

erlaubt sind. Das Semikolon hab ich beim Entfernen der Fußnote 
verschluckt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Übermäßig erleuchtend ist auch die rationale hier nicht:

``... While many implementations support more than two arguments to
main, such practice is neither blessed nor forbidden by the Standard;
a program that defines main with three arguments is not strictly
conforming (see §J.5.1.).''

Ähnlich dürfte also auch die Lage für »void main(void)« sein: not
strictly conforming, aber nicht verboten.  Daher halt auch kein
Fehler, sondern eine Warnung.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Könnte es sein, daß diese Diskussion reichlich akademisch ist? Auf 
welchem betriebssystemlosen System (und darum dürfte es sich wohl bei 
den meisten µCs hier handeln) ist es a) relevant, was der C-Startup-Code 
an main() übergibt und b) was main() zurückgibt? main() enthält auf µCs 
eine Endlosschleife, beendet sich also sowieso nicht ...

Nicht, daß ich kein Faible für sprachliche Spitzfindigkeiten hätte, auch 
"shall" ist wunderbar ("thou shalt commit adul_tery**", um mal ein 
quasiliterarisches Zitat* anzubringen) ...


*) "Good Omens" von Neil Gaiman und Terry Pratchett
**) GRR! "Your post seems to contain Spam: "ad*lt".

von Rolf Magnus (Gast)


Lesenswert?

> Könnte es sein, daß diese Diskussion reichlich akademisch ist?

Ja.

> Auf welchem betriebssystemlosen System (und darum dürfte es sich wohl
> bei den meisten µCs hier handeln) ist es a) relevant, was der
> C-Startup-Code an main() übergibt und b) was main() zurückgibt? main()
> enthält auf µCs eine Endlosschleife, beendet sich also sowieso
> nicht ...

Sagen wir's mal so: Wenn ich die Wahl hab, es formal korrekt zu machen 
oder so daß es mit ziemlicher Sicherheit immer noch funktioniert, aber 
eigentlich falsch ist, dann entscheide ich mich für ersteres.

von Rolf Magnus (Gast)


Lesenswert?

Übrigens ist das in C++ eindeutiger definiert. Aber daraus sollte man 
keine Rückschlüsse darauf ziehen, was in C eigentlich gemeint war. 
Trotzdem hier mal der entsprechende Ausschnitt aus 14882:
1
A program shall contain a global function called main, which is the designated start of the program. [...]
2
3
An implementation shall not predefine the main function. This function
4
shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations
5
shall allow both of the following definitions of main:
6
7
        int main() { /* ... */ }
8
9
  and
10
11
        int main(int argc, char* argv[]) { /* ... */ }

  

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.