Forum: Mikrocontroller und Digitale Elektronik expected declaration specifiers or '.' before '(' token


von Radler (Gast)


Lesenswert?

Hallo,
ich beschäftige mich gerade mit Flankenerkennung und da bin ich über den 
Artikel "High-Speed capture mit ATmega Timer" gestolpert.

Der dort veröffentlichte Code funktionierte auf Anhieb in der Arduino 
Umgebung, möchte ihn aber gerne auch im AVR Studio ohne die Arduino 
Libraries nutzen. Deshalb habe ich begonnen, den Code umzuschreiben.

Jetzt hänge ich bei:
1
 
2
const uint16_t projectRamUsage = 380 + 64;
3
const uint16_t bufSize ((RAMEND - 0x100 - projectRamUsage) / sizeof(uint16_t)); // use as much RAM as possible
4
const uint8_t RANGE_EXTENSION_BITS = 4; // factor for upper measurement range = 2^(RANGE_EXTENSION_BITS+1)

zu den mittleren Zeile spuckt der Kompiler folgenden Fehler aus:

Error  1  expected declaration specifiers or '...' before '(' token

Ich hätte jetzt hinter "bufSize" noch eine Zuweisung (=) erwartet, aber 
das ist nicht der Fehler.


Gruß
Radler

von Kibon (Gast)


Lesenswert?

[]

von Rolf F. (Firma: G.) (benutzername0)


Lesenswert?

Radler schrieb:
> Jetzt hänge ich bei:
>
>
1
> const uint16_t projectRamUsage = 380 + 64;
2
> const uint16_t bufSize ((RAMEND - 0x100 - projectRamUsage) / 
3
> sizeof(uint16_t)); // use as much RAM as possible
4
> const uint8_t RANGE_EXTENSION_BITS = 4; // factor for upper measurement 
5
> range = 2^(RANGE_EXTENSION_BITS+1)
6
>
>
> zu den mittleren Zeile spuckt der Kompiler folgenden Fehler aus:
>
> Error  1  expected declaration specifiers or '...' before '(' token

Klar, Garbage in - Garbage out.
Da fehlt etwas.

von Tom (Gast)


Lesenswert?

Der Compiler denkt, dass du eine Funktion bufSize deklarieren willst, 
die ein const uint16_t zurückgibt, und einen Fehler bei den Parametern 
gemacht hast. Daher die Fehlermeldung.

von Student (Gast)


Lesenswert?

Woran machst du fest, dass es nicht der Fehler ist?
() macht hier nur Sinn zur Gruppierung bzw. die äußere Klammer 
eigentlich gar keinen Sinn (bufSize ist ja keine Funktion).

Daher muss da sehr wohl ein = hin, du möchtest ja bufSize einen Wert 
zuweisen.
Und er sagt dir ja auch, er hat was vernünftiges erwartet, es fehlt 
etwas vor dem '('.

Die [] machen hier nur Sinn, wenn es zB uint16_t buf[bufSize]; wäre.

von Radler (Gast)


Lesenswert?

Mein erster Gedanke war halt auch, dass da ein "=" fehlt, also habe ich 
es hinzugefügt aber direkt eine weitere Fehlermeldung bekommen.

Ich werde es morgen noch mal probieren und die Meldung posten. Schonmal 
danke!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Student schrieb:
> Woran machst du fest, dass es nicht der Fehler ist?
> () macht hier nur Sinn zur Gruppierung bzw. die äußere Klammer

...oder wenn man C++ hat(te):  Das

int i(3);

durch

int i = 3;

zu ersetzen wird aber nicht funktionieren weil projectRamUsage in C 
keine CompileTime-Konstante ist.

Generell ist das, was der Code da anzustellen versucht, HACK — egal ob 
in C oder C++

von Rolf M. (rmagnus)


Lesenswert?

Radler schrieb:
> Der dort veröffentlichte Code funktionierte auf Anhieb in der Arduino
> Umgebung, möchte ihn aber gerne auch im AVR Studio ohne die Arduino
> Libraries nutzen.

Und anscheinend auch ohne C++.

Johann L. schrieb:
> ...oder wenn man C++ hat(te):  Das
>
> int i(3);
>
> durch
>
> int i = 3;
>
> zu ersetzen wird aber nicht funktionieren weil projectRamUsage in C
> keine CompileTime-Konstante ist.

Genau. In C würde man alles als #define schreiben.

von Radler (Gast)


Lesenswert?

also:
Wird ein "="-Zeichen eingefügt kommt folgende Fehlermeldung:

   Error  1  initializer element is not constant


Ersetze ich das const durch #define kommen zwei Warnungen zu der Zeile 
und 30 Errors unter anderem bei dem Array, dass duch "bufSize" definiert 
wird:

   Warning  1  data definition has no type or storage class [enabled by 
default]

   Warning  3  type defaults to 'int' in declaration of 'bufSize' 
[enabled by default]

   Error  5  initializer element is not constant



Wie müssten die Zeilen richtigerweise lauten?

Im Prinzip benötige ich auch gar nicht diese variable Definition des 
RAMs, da ich ja nicht ständig den µC wechsel.

Der Originale Code funktioniert ja mit 3 oder 4 µC...

Warum schluckt die Arduino IDE die Codezeilen problemlos und das AVR 
Studio nicht?


Gruß und Danke!
Radler

von Radler (Gast)


Lesenswert?

Nachtrag:

ich hatte vergessen das "uint16_t" zu löschen als ich es mit #define 
probiert habe.

Das habe ich jetzt gemacht:
1
#define bufSize ((RAMEND - 0x100 - projectRamUsage) / sizeof(uint16_t)) // use as much RAM as possible

jetzt kommt nur noch eine Fehlermeldung ist der Zeile:
1
uint16_t captureData[bufSize]; // the buffer where the catured data is stored

   Error  1  variably modified 'captureData' at file scope

von Carl D. (jcw2)


Lesenswert?

Es gibt da ein magisches Wort names static, das macht aus nicht 
änderbaren Variablen Compiletime-Konstanten. Nur solche können ein 
globales Array dimensionieren.
1
 
2
static const uint16_t projectRamUsage = 380 + 64;
3
static const uint16_t bufSize = ((RAMEND - 0x100 - projectRamUsage) / sizeof(uint16_t)); // use as much RAM as possible
4
static const uint8_t RANGE_EXTENSION_BITS = 4; // factor for upper measurement range = 2^(RANGE_EXTENSION_BITS+1)

Oder man verzichtet auf ein paar Byte RAM und holt sich den Buffer per 
malloc().

: Bearbeitet durch User
von Radler (Gast)


Lesenswert?

so ich habs hinbekommen...

nachdem ich alle drei Zeilen mit #define versehen habe, ist es 
fehlerfrei.
1
#define projectRamUsage  380 + 64
2
#define bufSize ((RAMEND - 0x100 - projectRamUsage) / sizeof(uint16_t)) // use as much RAM as possible
3
#define RANGE_EXTENSION_BITS  4 // factor for upper measurement range = 2^(RANGE_EXTENSION_BITS+1)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Radler schrieb:
> #define projectRamUsage  380 + 64

Das solltest Du sicherheitshalber klammern.

Sieh Dir mal an, was hier passieren würde:

int a = 10 * projectRamUsage;

Wie groß ist a?

von Carl D. (jcw2)


Lesenswert?

Radler schrieb:
> so ich habs hinbekommen...
>
> nachdem ich alle drei Zeilen mit #define versehen habe, ist es
> fehlerfrei.
>
>
1
#define projectRamUsage  380 + 64
2
> #define bufSize ((RAMEND - 0x100 - projectRamUsage) / sizeof(uint16_t)) 
3
> // use as much RAM as possible
4
> #define RANGE_EXTENSION_BITS  4 // factor for upper measurement range = 
5
> 2^(RANGE_EXTENSION_BITS+1)

static const wäre die typesave Variante.

von Radler (Gast)


Lesenswert?

Carl D. schrieb:
> static const wäre die typesave Variante.

habs probiert, erzeugte zwei Errors:
1
static const uint16_t bufSize = ((RAMEND - 0x100 - projectRamUsage) / sizeof(uint16_t)); // use as much RAM as possible

   Error  1  initializer element is not constant

1
uint16_t captureData[bufSize]; // the buffer where the catured data is stored

   Error  2  variably modified 'captureData' at file scope

von Rolf F. (Firma: G.) (benutzername0)


Lesenswert?

Radler schrieb:

Das bufSize sollte konstant gesetzt werden, z. B. per define(s), dann 
sollte es gehen.

von Radler (Gast)


Lesenswert?

Habe noch eine Frage:

Progamm lässt sich jetzt im AVR Studio kompilieren und funktioniert auch 
soweit, aber die eingestellte Baudrate stimmt nicht ganz.
Ich muss im Programm eine Baudrate von 110000 definieren, damit HTerm 
das richtige bei 115200Baud ausspuckt.

Läuft mein µC zu schnell?

Ich nutzte eine UART initialisierung die glaub hier aus einem Artikel 
stammt, die bis jetzt auch immer sehr gute Dienste geleistet hat.

Gruß
Radler

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Radler schrieb:
> Läuft mein µC zu schnell?

Nach Deinen Zahlen läuft Dein µC um den Faktor 1,05 zu schnell. Hast Du 
denn einen Quarz angeschlossen?

Beschreibe doch mal Deinen Aufbau vollständig (Foto wäre auch ganz gut) 
und zeige insbesondere die "UART initialisierung die glaub hier aus 
einem Artikel stammt, die bis jetzt auch immer sehr gute Dienste 
geleistet hat."

Bitte nicht immer alles aus der Nase ziehen lassen. Macht keinen Spaß.

von Rolf Magnus (Gast)


Lesenswert?

Radler schrieb:
> Warum schluckt die Arduino IDE die Codezeilen problemlos und das AVR
> Studio nicht?

Wie schon mehrmals gesagt wurde: Weil du es offenbar bei ersterer als 
C++-Code übersetzt, bei letzerer aber als C-Code.
Und in C müssen Initialisierungswerte globaler Variablen immer 
Konstanten sein. Da eine const-Variable nunmal keine echte 
Compilezeit-Konstante ist, kann man sie nicht zur Initialisierung einer 
anderen verwenden, so wie du das oben mit programRamUsage zur 
Initialisierung von bufsizes machst. Außerdem gibt's Initialisierungen 
im Konstruktor-Style wie oben die von bufsize in C nicht.

Radler schrieb:
> Progamm lässt sich jetzt im AVR Studio kompilieren und funktioniert auch
> soweit, aber die eingestellte Baudrate stimmt nicht ganz.
> Ich muss im Programm eine Baudrate von 110000 definieren, damit HTerm
> das richtige bei 115200Baud ausspuckt.
>
> Läuft mein µC zu schnell?

Scheint so. Mit welchem Quarz betreibst du den µC denn?

Carl D. schrieb:
> Es gibt da ein magisches Wort names static, das macht aus nicht
> änderbaren Variablen Compiletime-Konstanten.

Mit Verlaub: Das ist Blödsinn.

von Radler (Gast)


Angehängte Dateien:

Lesenswert?

Ok sorry!
Zum Aufbau: Zwei Arduino Nano. Der eine schaltet einen Pin in einer 
gewissen Reihenfolge ein und wieder aus, mehr nicht.
Mit dem anderen Taste ich das Signal ab und gebe mir die Einschalt/ 
Ausschaltzeiten über UART am HTerm aus.

Setzte ich die Baudrate runten, läuft alles synchron (zb 9600) und bei 
hohen Raten muss ich "nachregeln"

Im Anhang die Initialisierung.

Wenn ich so recht überlege, habe ich noch nie höhe Baudraten gebraucht, 
wodurch mir der Fehler somit noch nicht aufgefallen ist.

von Operator S. (smkr)


Lesenswert?

Man sollte in jedem Fall typsichere Variablen einem define vorziehen.
In deinem Fall müsste der alte "enum-hack" weiterhelfen:
1
enum { projectRamUsage = 380+64 };
2
static const uint16_t bufSize = ((RAMEND - 0x100 - projectRamUsage) / sizeof(uint16_t)); 
3
static const uint8_t RANGE_EXTENSION_BITS = 4;

So müsste es gehen

von Rolf M. (rmagnus)


Lesenswert?

Und ein enum soll typsicherer sein als ein #define, bei dem ich im 
Gegensatz dazu den Typ auch explizit angeben kann?
1
#define PROGRAM_RAM_USAGE (380UL + 64UL)
Zur Not auch:
1
#define PROGRAM_RAM_USAGE (unsigned long)(380 + 64)

Operator S. schrieb:
1
> enum { projectRamUsage = 380+64 };
2
> static const uint16_t bufSize = ((RAMEND - 0x100 - projectRamUsage) / sizeof(uint16_t));
3
> static const uint8_t RANGE_EXTENSION_BITS = 4;
>
> So müsste es gehen

Nein, das wird spätestens hier nicht mehr funktionieren:

Radler schrieb:
1
> uint16_t captureData[bufSize]; // the buffer where the catured data is  stored

: Bearbeitet durch User
von Operator S. (smkr)


Lesenswert?

Rolf M. schrieb:
> Und ein enum soll typsicherer sein als ein #define

Ja, immer.
Aber es ist wie gesagt ein hack. Die erste Limitation tritt schon auf, 
wenn man einen anderen Variablentyp als int braucht, dann kann mal 
keinen enum mehr einsetzen.

Für genau diesen Fall ist ein enum aber besser, da der Compiler die 
Variable einsetzt und nicht das define. Dies hat z.B. bei Compilefehlern 
den Vorteil, dass der Name angezeigt wird und nicht bloss eine Nummer. 
Beim Fehler am Ort: 380+64 weiss man unter Umständen nicht, wo das ist.
Ein weiterer Vorteil tritt bei mehrfacher Verwendung dieser Variablen 
auf. Der Compiler verbraucht nur einmal diesen Speicher, da er weiss das 
es eine konstante Variable ist, mit mehrfacher Verwendnung. Bei einem 
define wird aber überall der Wert vom Preprozessor eingesetzt, womit zu 
Compilezeit die Relationen zueinander verloren gehen.

von Rolf Magnus (Gast)


Lesenswert?

Operator S. schrieb:
> Ein weiterer Vorteil tritt bei mehrfacher Verwendung dieser Variablen
> auf. Der Compiler verbraucht nur einmal diesen Speicher, da er weiss das
> es eine konstante Variable ist, mit mehrfacher Verwendnung. Bei einem
> define wird aber überall der Wert vom Preprozessor eingesetzt, womit zu
> Compilezeit die Relationen zueinander verloren gehen.

Compiler sind da erstaunlich gut. gcc erkennt z.B. auch, wenn das 
gleiche String Literal an mehreren Stellen im Code eingesetzt wird und 
führt das zusammen. Sogar bei einem "Hello world" und einem "world" wird 
nur der erste String gespeichert und für den zweiten einfach mitbenutzt.
Und ob bei einem Integer der Wert überhaupt gespeichert werden muss, ist 
dann auch wieder die Frage. Ggf. wird er einfach als immediate in ein 
Register geladen und fertig. Das ist einfacher und platzsparender, als 
erst die Adresse zu laden und dann von der Stelle aus dem Speicher zu 
lesen.

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.