Forum: Compiler & IDEs Wie richtig geschweifte Klammern {} setzen?


von hartwig (Gast)


Lesenswert?

Ich erzeuge mittels eines Scriptes C-Code. Ein Beispiel, Datei m.c:
1
struct note {
2
    short time;
3
    char note, vel;
4
};
5
6
struct mfile {
7
    char name[10];
8
    char time1, time2, time3, time4;
9
    struct note notes[];
10
};    
11
12
struct mfile _name01 = 
13
{
14
    "name01" ,    //Name
15
    4, 4, 24, 8,  //TimeSig
16
    0, 36, 112,    //NoteOn, vel
17
    120, 60, 113,  //NoteOn, vel
18
    240, 38, 127,  //NoteOn, vel
19
    0, 0, 0 
20
};

Das Beispiel kompiliert und erzeugt auch das gewünschte Objectfile 
(überprüft mit objdumb -s), wirft aber bei -Wall Warnings:
1
$ gcc -c m.c -Wall
2
m.c:14:1: warning: missing braces around initializer [-Wmissing-braces]
3
   14 | {
4
      | ^
5
......
6
   17 |     0, 36, 112,         //NoteOn, vel
7
      |     {{        }
8
   18 |     120, 60, 113,       //NoteOn, vel
9
      |     {           }
10
   19 |     240, 38, 127,       //NoteOn, vel
11
      |     {           }
12
   20 |     0, 0, 0
13
      |     {
14
   21 | };
15
      | }}

Jetzt habe ich in der letzten Stunde diverse Versuche unternommen, die 
geschweiften Klammern zu setzen, schaffe es aber nicht, dass das 
Kompilat ohne Warnings durchgeht. Schlimmer noch, meistens werden sogar 
Fehler generiert. Ich stehe irgendwie auf dem Schlauch. Wie mache ich 
das richtig?

von hartwig2 (Gast)


Lesenswert?

Hm... ich hatte anscheinend Tomaten auf den Augen: So gehts
1
struct mfile _name01 = 
2
{
3
    "name01" ,          //Name
4
    4, 4, 24, 8,        //TimeSig
5
    {{ 0, 36, 112},     //NoteOn, vel
6
    {120, 60, 113},     //NoteOn, vel
7
    {240, 38, 127},     //NoteOn, vel
8
    {0, 0, 0}} 
9
};

von Rolf M. (rmagnus)


Lesenswert?

hartwig2 schrieb:
> struct mfile _name01 =
> {
>     "name01" ,          //Name
>     4, 4, 24, 8,        //TimeSig
>     {{ 0, 36, 112},     //NoteOn, vel
>     {120, 60, 113},     //NoteOn, vel
>     {240, 38, 127},     //NoteOn, vel
>     {0, 0, 0}}

Statt in Kommentaren zu erwähnen, was die Werte bedeuten, kannst du auch 
einfach mit Namen initialisieren. Ich würde es so schreiben:
1
struct mfile _name01 =
2
{
3
    .name = "name01",
4
    .time1 = 4,
5
    .time2 = 4,
6
    .time3 = 24,
7
    .time4 = 8,
8
    .notes = 
9
    {
10
        { .time = 0,   .note = 36, .vel = 112 },
11
        { .time = 120, .note = 60, .vel = 113 },
12
        { .time = 240, .note = 38, .vel = 127 },
13
        { 0, 0, 0 }
14
    }
15
};

von Peter D. (peda)


Lesenswert?

Ich bevorzuge auch die Memberschreibweise. Dann kann man weitere Member 
einfügen oder sie umsortieren.

von W.S. (Gast)


Lesenswert?

hartwig schrieb:
> struct note notes[];

So etwas ärgert mich mehr, als unleserlich gesetzte Klammern. Es ist dem 
Compiler zwar egal, ob du deinen struct 'note' oder 'karlheinz' nennst, 
aber bei Typnamen sollte man sich der Lesbarkeit zuliebe etwas mehr 
eigene Disziplin gönnen.
So zum Beispiel anstelle 'note' lieber 'Tnote' oder wer es andersherum 
lieber mag dann eben 'note_t' oder so ähnlich.

W.S.

von Hans Wurscht (Gast)


Lesenswert?

Verstehe ich jetzt nicht was an einem vor oder nachgestelltem t 
übersichtlicher sein soll.

von DPA (Gast)


Lesenswert?

Am besten immer alles in einzahl schreiben:

struct note note[];

von Nachdenklicher (Gast)


Lesenswert?

Ein Array ist Mehrzahl, weil mehrere Elemente. Da ist ein Pluralname 
auch sinnvoll.

Außerdem ermöglicht es, wenn man einzelne Elemente anschaut, 
beispielsweise innerhalb einer for-Schleife so etwas wie
1
note = notes[i]
 (note ist eine Variable des gleichen Typs wie die Elemente des Arrays 
notes)

Sonst muß man sich erst irgendeinen Namen für die Variable aus den 
Fingern saugern, wenn das Array schon so heißt...

von Quelltextleserversteher (Gast)


Lesenswert?

Hans Wurscht schrieb:
> Verstehe ich jetzt nicht was an einem vor oder nachgestelltem t
> übersichtlicher sein soll.

Nicht unbedingt im Kontext o.g. Codeschnipsels.

Aber anderswo in mitten von Code, wenn eine lokale Variable nötig ist, 
hilft es einem Typ-Bezeichner von Instanz-Bezeichner sofort und 
unmissverständlich auseinander zu halten.

Insgesamt werden Typ-Bezeichner weniger Häufig als Instanz-Bezeichner 
geschrieben, also tut ein kleines zus. Artefakt wie eben "_t" suffix 
weniger "weh".

Ist bloss eine Konvention und dem Compiler egal, aber vielleicht 
schreibst Du ja lieber "Write-once, Read-never"-Code...
Oder du machst auf Retro, mit einem vintage-Compiler der bloss die 
ersten 8 Zeichen von Bezeichner berücksichtigt...

---

N.B: "note[i]" ist ein Element aus dem Array, warum sollte das in 
Mehrzahl geschrieben sein? ;-)

von Nachdenklicher (Gast)


Lesenswert?

Quelltextleserversteher schrieb:
> N.B: "note[i]" ist ein Element aus dem Array, warum sollte das in
> Mehrzahl geschrieben sein? ;-)

Richtig, aber...
Das Array, wenn es zur Gänze überben wird, beispielsweise an eine 
Funktion, sollte seine Pluraliät aber durch den Namen zeigen können - 
und das kann es mit einem Singularnamen nicht. wenn ich irgendwo
1
foo = bar(note);
 aufrufe, wie sehe ich dann, daß note eigentlich ein Array ist? ;-)

Ein Pluralname, der ein einzelnes Objekt durch den Indexoperator [] 
herausstellt, ist für mich da logischer.

von 🐧 DPA 🐧 (Gast)


Lesenswert?

Nachdenklicher schrieb:
> Ein Array ist Mehrzahl, weil mehrere Elemente. Da ist ein Pluralname
> auch sinnvoll.
>
> Außerdem ermöglicht es, wenn man einzelne Elemente anschaut,
> beispielsweise innerhalb einer for-Schleife so etwas wie
> note = notes[i]

"note" ist aber in dem Beispiel hier in einem struct, also hätte man 
sowieso note = something->note[i]. Falls man eine globale variable hat, 
muss man sowieso noch hinschreiben, wozu das gehört, sonst hat man 
plötzlich irgendwo 2 notes. Und falls man local doch schon eine note 
variable hat, kann man auch etwas wie "note2" oder "it" nehmen. 
Alternativ könne man auch es auch list_note oder note_list nennen. Der 
Vorteil davon, ist immer noch Einzahl, und lönnte man wiederhohlen. z.B. 
node_list_list. Ist auch einheitlicher. Hat man z.B. "dice", ist die 
Mehrzahl auch "dice", da hätte man also sonst ein Problem, wenn man es 
daran fest machen will.

Nachdenklicher schrieb:
> foo = bar(note);
>  aufrufe, wie sehe ich dann, daß note eigentlich ein Array ist?

Da keine länge übergeben wird, wird bar wohl schon nur 1 Element 
verwenden.

von A. S. (Gast)


Lesenswert?

Quelltextleserversteher schrieb:
> hilft es einem Typ-Bezeichner von Instanz-Bezeichner sofort und
> unmissverständlich auseinander zu halten.

Im Original wird doch struct davorgesetzt :-)

Ja, es tut nicht weh, ist sinnvoll. Aber ein _t oder ähnlich sollte 
typedefs vorbehalten bleiben.

Ich denke, sein Geschmack bei Pascal ist besser weil er Pascal kennt und 
lebt.

von A. S. (Gast)


Lesenswert?

🐧 DPA 🐧 schrieb:
> . Hat man z.B. "dice", ist die Mehrzahl auch "dice",

Das problem.kann man dann gesondert lösen. Aber ein Array in Einzahl 
nennen und dann zig workarounds dafür ist unsinnig.

note=notes[3] ist an Klarheit kaum zu überbieten. Element [3] der notes. 
Und auch beim Funktionsaufruf sollte f(note) von g(notes) und 
f(notes[i]) unterscheidbar sein.

von Nachdenklicher (Gast)


Lesenswert?

🐧 DPA 🐧 schrieb:
> Da keine länge übergeben wird, wird bar wohl schon nur 1 Element
> verwenden.

Nicht unbedingt. In meinem täglichen Umfeld gibt es oft Tabellen als 
Array von bestimmten Strukturen, in denen das Ende des Arrays durch 
einen bestimmten Wert definiert wird.

(vereinfachtes) Beispiel
1
// commands.h
2
typedef struct 
3
{
4
    char* command,
5
    uint8_t num_params,
6
    // weiteres Gerödel, was einen Befehl auf interne Funktionen abbildet
7
} command_t;
8
(...)
9
command_t* find_command(char* command_string);
10
11
extern command_t standard_commands[];
12
13
14
// commands.c
15
command_t standard_commands[] = 
16
{
17
    {"foo", 42, /* was halt noch so gebraucht wird */ },
18
    (...weitere Befehle...)
19
    {NULL, 0, /*...*/}
20
};
21
22
command_t admin_commands[] = 
23
{
24
    (...weitere Befehle, die nur der Admin darf...)
25
};
26
27
command_t* find_command(command_t[] command_table, char* command_string)
28
{
29
    (...)
30
}
31
// Ganz wo anders
32
#include commands.h
33
34
(...)
35
36
command_t* command;
37
38
(...)
39
40
command = find_command(standard_commands, user_input);

Die Funktion geht dann einfach durchs Array, bis "command" NULL ist, was 
das Ende der Liste markiert.

Falls sich einer fragt, warum keine Member-Schreibweise bei der 
Initialisierung von commands - unser Compiler kann das noch nicht, der 
steht rigendwo zwischen C89 und C99. Ist halt ein etwas betagterer 
welcher.

von hartwig (Gast)


Lesenswert?

Rolf M. schrieb:
> Statt in Kommentaren zu erwähnen, was die Werte bedeuten, kannst du auch
> einfach mit Namen initialisieren. Ich würde es so schreiben:

Ah, ok. Wusste gar nicht, dass dies so geht. Danke! Wieder was gelernt!

Zur Diskussion note vs notes[] mache ich mir mal Gedanken. Evtl. könnte 
die Definition am Anfang einen Großbuchstaben haben, z.B.
struct Note {...}; vs struct Note notes[];

von Klaus W. (mfgkw)


Lesenswert?

hartwig schrieb:
> Ah, ok. Wusste gar nicht, dass dies so geht.

je nach C-Version...

hartwig schrieb:
> Zur Diskussion note vs notes[] mache ich mir mal Gedanken. Evtl. könnte
> die Definition am Anfang einen Großbuchstaben haben, z.B.
> struct Note {...}; vs struct Note notes[];

In C++ ist es gängig, gerade andersrum zu verfahren:
Klassennamen (die ja Typnamen sind) mit einem Großbuchstaben zu 
beginnen, die Objekte/Instanzen/Variablen... dann mit einem kleinen.
1
struct Node
2
{
3
  ...
4
};
5
6
class BessererNode: public Node
7
{
8
   ...
9
};
10
11
...
12
13
Node          einNode, nocheinNode;
14
BessererNode  einBessererNode;
15
BessererNode  vieleBessereNodes[nNodes];
Wenn du dir schon ein Regelwerk überlegst, dann vielleicht eher sorum?

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

hartwig schrieb:
> Zur Diskussion note vs notes[] mache ich mir mal Gedanken. Evtl. könnte
> die Definition am Anfang einen Großbuchstaben haben, z.B.
> struct Note {...}; vs struct Note notes[];

Wenn du jetzt mit Groß/Kleinbuchstaben anfängst, dann ergibt das recht 
bald eine herzlich unleserliche Quelle. Nein, aus Dingen wie groß versus 
klein ergibt sich keine bessere Lesbarkeit. Da ist jedes Stilmittel, das 
irgend eine verbale Beziehung hat zum Wort "Typ" weitaus besser. Aber 
OK, man kann das alles auch "karlheinz" nennen oder "v427af60" - bloß ob 
das lesbarer ist, wage ich zu bezweifeln.

W.S.

von Rolf M. (rmagnus)


Lesenswert?

A. S. schrieb:
> Quelltextleserversteher schrieb:
>> hilft es einem Typ-Bezeichner von Instanz-Bezeichner sofort und
>> unmissverständlich auseinander zu halten.
>
> Im Original wird doch struct davorgesetzt :-)

Ich finde es immer lustig, wenn jemand sich ein typedef bastelt, um das 
struct wegzulassen und sich dann Gedanken darüber macht, wie er in den 
Namen reinkodiert, dass es eine struct ist.

Klaus W. schrieb:
> hartwig schrieb:
>> Ah, ok. Wusste gar nicht, dass dies so geht.
>
> je nach C-Version...

Da muss man aber schon weit zurückgehen (ins vergangene Jahrtausend), um 
eine C-Version zu finden, die das noch nicht hat.

von A. S. (Gast)


Lesenswert?

W.S. schrieb:
> Nein, aus Dingen wie groß versus
> klein ergibt sich keine bessere Lesbarkeit

Da es nicht allzu viele Stilmittel gibt, sollte man Groß-Schreibung 
nicht ausschließen. CamelCase oder DEFINES_GROSS sind ja auch geläufig. 
Ein Prä/Postfix-T ist nicht per se schlechter als t_ oder _t.

Solange Namensregeln (also wie Namen gebildet werden) und Typo 
(groß/klein/Unterstrich) konsistent, redundant und lesbar sind, macht es 
wenig Sinn, sich über einen davon Aspekt ein Urteil zu erlauben.

(Aber ja, das mag in Pascal anders sein, weil es generell geschwätziger 
ist. Nicht als Nachteil, nur als Unterschied).

von Cartman (Gast)


Lesenswert?

Um mal auf den Ausgangspunkt:
"Wie richtig geschweifte Klammern {} setzen?"
zurueckzukommen, das ist doch einfach.

Schreib dir 2 Makros:

#define BEGIN {
#define END }

Schon bist du die Sorge um diese e(c)kligen Klammern los,
und kannst wie der Pascalprofi mit BEGIN und END um dich werfen.

Deine Kollegen werden begeistert sein!

von Cartman (Gast)


Lesenswert?

Falls deine Kollegen Pascal nicht moegen, was vorkommen soll,
bietet sich folgende kreative Variante an:
1
#define SCHNIPP {
2
#define SCHNAPP }
3
4
struct mfile _name01 = 
5
6
SCHNIPP 
7
    "name01" ,          //Name
8
    4, 4, 24, 8,        //TimeSig
9
    SCHNIPP SCHNIPP  0, 36, 112 SCHNAPP,     //NoteOn, vel
10
    SCHNIPP 120, 60, 113 SCHNAPP,     //NoteOn, vel
11
    SCHNIPP 240, 38, 127 SCHNAPP,     //NoteOn, vel
12
    SCHNIPP 0, 0, 0 SCHNAPP SCHNAPP  
13
SCHNAPP;

von Cartman (Gast)


Lesenswert?

Beim dritten Bier faellt mir bestuemmpt nochwas ein.

von hartwig (Gast)


Lesenswert?

@Cartman: Dir ist aber schon klar, dass W.S. nicht der Threadstarter 
ist.

von Cartman (Gast)


Lesenswert?

> ich hatte anscheinend Tomaten auf den Augen
Ja.

> Dir ist aber schon klar
Ich hab doch keine Tomaten auf den Augen.

Aber ich hatte mal einen "lustigen" Effekt, wo ein syntaktisch
nicht falsches, aber unnoetiges Semikolon den Koempeiler zu einem
kaprizioesen Verhalten animiert hat.
Sowas aber auch...

Ich weiss gar nicht mehr wie ich das gefunden hab,
ich glaub mit dem Debuegger. Da sah man das sofffort.
-Wall konnte/kann/kennt der naemlich nicht.

von c-hater (Gast)


Lesenswert?

Cartman schrieb:
> Aber ich hatte mal einen "lustigen" Effekt, wo ein syntaktisch
> nicht falsches, aber unnoetiges Semikolon den Koempeiler zu einem
> kaprizioesen Verhalten animiert hat.

ganz bestimmt...

von tut nix zur Sache (Gast)


Lesenswert?

Wie wär's mit:

int array[1][5]
=
<%
  <% 1, 2, 3, 4, 5
  %>
%>;

Sieht schön aus und macht die Sache noch lesbarer ^^

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.