Forum: Mikrocontroller und Digitale Elektronik C-Funktion verstehen


von Ralf (Gast)


Lesenswert?

Hallo,

meine C-Kenntnisse sind eingerostet kann mir bitte einer hierbei 
weiterhelfen?
1
void stepper_set_soll_position (unsigned long ulNewPosition, unsigned char ucMotor)
2
{
3
  ulNewPosition &= (unsigned long)(~1);
4
5
  ucMotor &= 1;
6
}

Was passiert in dieser Zuweisung
1
 ulNewPosition &= (unsigned long)(~1);
 und wofür könnte es gut sein in der Funktion?

von STK500-Besitzer (Gast)


Lesenswert?

Ralf schrieb:
> Was passiert in dieser Zuweisung ulNewPosition &= (unsigned long)(~1);
> und wofür könnte es gut sein in der Funktion?

ein Cast auf unsigned long einer bitweisen negation der 1 wird mit 
ulNewPosition verundet und in ulNewPosition gespeichert.

von Dussel (Gast)


Lesenswert?

Gerhard O. schrieb im Beitrag #4920606:
> Aber wie gesagt, das funktioniert nur wenn die Inputparameter Global
> sind weil diese Funktion nichts zurück geben kann.
Meines Wissens noch nichtmal dann, weil die Neudefinition die globale 
Definition innerhalb der Funktion überdeckt.

von Stefan S. (energizer)


Lesenswert?

(unsigned long)(~1);

ist in binärer Schreibweise 11111111111111111111111111111110, also 
4294967294 dezimal. Mit

ulNewPosition &= (unsigned long)(~1);

wird also das niedrigste Bit in ulNewPosition gelöscht.

Stefan

von Joe F. (easylife)


Lesenswert?

Wie Dussel sagt: diese Funktion bewirkt rein gar nichts.

von Mark B. (markbrandis)


Lesenswert?

Ralf schrieb:
>
1
> 
2
> void stepper_set_soll_position (unsigned long ulNewPosition, unsigned 
3
> char ucMotor)
4
> {
5
>   ulNewPosition &= (unsigned long)(~1);
6
> 
7
>   ucMotor &= 1;
8
> }
9
> 
10
>

So wie die Funktion implementiert ist, macht sie vom Ergebnis her genau 
gar nichts.

Es gibt drei sinnvolle Möglichkeiten:

1.) Entweder die Variablen ulNewPosition und ucMotor sind global 
deklariert. Dann ergibt es keinen Sinn, sie der Funktion auch noch zu 
übergeben.

2.) Oder man übergibt der Funktion die Adressen der Variablen, die 
anderswo deklariert sind. Dann brauchen sie nicht global zu sein und man 
kann per Derefenzierung auf sie zugreifen.

3.) Oder man übergibt die Variablen an die Funktion, so wie hier, so 
dass sie auf dem Stack liegen. Dann sollte die Funktion aber auch etwas 
zurückgeben und nicht als void deklariert sein.

von Joe F. (easylife)


Lesenswert?

Die übergebenen Variablen landen auf dem Stack, werden dann wie auch 
immer verändert und dann weggeschmissen. Ein guter Compiler optimiert 
die gesamte Funktion einfach weg.

von Peter D. (peda)


Lesenswert?

Joe F. schrieb:
> Wie Dussel sagt: diese Funktion bewirkt rein gar nichts.

Mit etwas Grips könnte man sich leicht denken, daß er nur die ihm 
unverständlichen Zeilen gepostet hat.
Vollständige Funktionen sieht man hier nur sehr selten.

Das Optimum wäre gewesen, die fraglichen Zeilen im Beitrag zu zitieren 
und den kompletten, echten Code als Anhang.

von Mark B. (markbrandis)


Lesenswert?

Peter D. schrieb:
> Joe F. schrieb:
>> Wie Dussel sagt: diese Funktion bewirkt rein gar nichts.
>
> Mit etwas Grips könnte man sich leicht denken, daß er nur die ihm
> unverständlichen Zeilen gepostet hat.

Das ändert doch aber nichts daran, dass die Funktion so nicht 
funktioniert.

von Hans-Georg L. (h-g-l)


Lesenswert?

S. S. schrieb:
> (unsigned long)(~1);
>
> ist in binärer Schreibweise 11111111111111111111111111111110, also
> 4294967294 dezimal. Mit
>
Bist du dir sicher ?

Die Ziffer 1 ist erst einmal ein integer der bitweise negiert wird und 
wenn du den auf einen long castest wird er mit mit 0 und nicht mit 1 
vorne aufgefüllt.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Hans-Georg L. schrieb:
> Die Ziffer 1 ist erst einmal ein integer der bitweise negiert wird und
> wenn du den auf einen long castest wird er mit mit 0 und nicht mit 1
> vorne aufgefüllt.

"sign expansion", anyone?

von Peter D. (peda)


Lesenswert?

Hans-Georg L. schrieb:
> Die Ziffer 1 ist erst einmal ein integer der negiert wird und wenn du
> den auf einen long castest wird er mit mit 0 und nicht mit 1 vorne
> aufgefüllt.

Guter Einwand, so ists richtig:
1
~(unsigned long)1
oder
1
~1UL

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hans-Georg L. schrieb:
> Die Ziffer 1 ist erst einmal ein integer der negiert wird und wenn du
> den auf einen long castest wird er mit mit 0 und nicht mit 1 vorne
> aufgefüllt.

Das klingt erstmal logisch, ein Versuch belehrt mich aber eines 
besseren:
1
#include <stdio.h>
2
#include <stdint.h>
3
4
int main()
5
{
6
    printf ("sizeof(int):  %ld\n", sizeof(int));
7
    printf ("sizeof(long): %ld\n", sizeof(long));
8
9
    printf ("%x\n", ~1);
10
    printf ("%lx\n", ~1L);
11
    printf ("%lx\n", (unsigned long)(~1));
12
    printf ("%lx\n", (unsigned long)(~1U));
13
    return 0;
14
}
1
$ cc a.c && ./a.out
2
sizeof(int):  4
3
sizeof(long): 8
4
fffffffe
5
fffffffffffffffe
6
fffffffffffffffe
7
fffffffe

Es liegt an der Sign-Extension, dass "(unsigned long)(~1)" trotzdem 
funktioniert. Rufus hatte den richtigen Riecher.

von Mark B. (markbrandis)


Lesenswert?

Ich finde es interessant, wie hier so gerne auf Details der 
Implementierung herumgeritten wird, wenn das ganze Code-Beispiel an sich 
Müll ist und entsorgt gehört. ;-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Mark B. schrieb:
> Ich finde es interessant, wie hier so gerne auf Details der
> Implementierung herumgeritten wird, wenn das ganze Code-Beispiel an sich
> Müll ist und entsorgt gehört. ;-)

Ich finde es eher interessant, dass Du einen Auszug aus einer Funktion 
nicht akzeptierst und darauf herumreitest. Es ging darum, was eine 
einzelne Zeile bewirkt und nicht darum, was eine ganze Funktion bewirkt.

Der Korinther bist Du, nicht die anderen.

von Dussel (Gast)


Lesenswert?

Mark B. schrieb:
> 1.) Entweder die Variablen ulNewPosition und ucMotor sind global
> deklariert. Dann ergibt es keinen Sinn, sie der Funktion auch noch zu
> übergeben.
Ich habe es gerade mal kurz mit XCode (meines Wissens gcc) getestet
1
#include <iostream>
2
using std::cout;
3
using std::cin;
4
5
unsigned short int global;
6
7
void Funktion(unsigned short int global);
8
9
int main()
10
{
11
  unsigned short int lokal=5;
12
  global=3;
13
  
14
  Funktion(lokal);
15
  
16
  cout<<"lokal="<<lokal<<"; global="<<global<<"\n";
17
  
18
  return 0;
19
}
20
21
void Funktion(unsigned short int global)
22
{
23
  global=10;
24
}
ergibt als Ausgabe
lokal=5; global=3

Das heißt, wie ich oben schrieb, wird die globale Variable von der 
lokalen Deklaration überdeckt.

von Clemens L. (c_l)


Lesenswert?

Hans-Georg L. schrieb:
> S. S. schrieb:
>> (unsigned long)(~1);
>>
>> ist in binärer Schreibweise 11111111111111111111111111111110, also
>> 4294967294 dezimal. Mit
>>
> Bist du dir sicher ?
>
> Die Ziffer 1 ist erst einmal ein integer der bitweise negiert wird und
> wenn du den auf einen long castest wird er mit mit 0 und nicht mit 1
> vorne aufgefüllt.

C99 § 6.3.1.1:
> 1 When a value with integer type is converted to another integer type
>   other than _Bool, if the value can be represented by the new type,
>   it is unchanged.

"1" ist vom Typ "int", also signed, und deshalb auch "~1", also ist "~1" 
negativ (-2), also kann dieser Wert in "unsigned long" nicht 
repräsentiert werden.

> 2 Otherwise, if the new type is unsigned, the value is converted by
>   repeatedly adding or subtracting one more than the maximum value
>   that can be represented in the new type until the value is in the
>   range of the new type.

Dieses Verfahren impliziert, dass ein kleinerer Typ mit dem 
Vorzeichen-Bit aufgefüllt wird, d.h., das Ergebnis ist das selbe wie bei 
"(unsigned long)-2".

von Mark B. (markbrandis)


Lesenswert?

Frank M. schrieb:
> Mark B. schrieb:
>> Ich finde es interessant, wie hier so gerne auf Details der
>> Implementierung herumgeritten wird, wenn das ganze Code-Beispiel an sich
>> Müll ist und entsorgt gehört. ;-)
>
> Ich finde es eher interessant, dass Du einen Auszug aus einer Funktion
> nicht akzeptierst und darauf herumreitest. Es ging darum, was eine
> einzelne Zeile bewirkt und nicht darum, was eine ganze Funktion bewirkt.
>
> Der Korinther bist Du, nicht die anderen.

Man muss schon ziemlich blind sein oder ein völlig unfähiger 
Programmier, um den hier gezeigten Code in irgend einer Weise als 
sinnvoll zu bezeichnen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Mark B. schrieb:
> Man muss schon ziemlich blind sein oder ein völlig unfähiger
> Programmier, um den hier gezeigten Code in irgend einer Weise als
> sinnvoll zu bezeichnen.

Es ging nicht um die Sinnigkeit/Unsinnigkeit. Aber wenn Du das so mit 
dem "unfähigen Programmierer" so siehst, akzeptiere ich das ;-)

von Hans-Georg L. (h-g-l)


Lesenswert?

Rufus Τ. F. schrieb:
> Hans-Georg L. schrieb:
>> Die Ziffer 1 ist erst einmal ein integer der bitweise negiert wird und
>> wenn du den auf einen long castest wird er mit mit 0 und nicht mit 1
>> vorne aufgefüllt.
>
> "sign expansion", anyone?

Du hast recht es wird eine negativer integer daraus. Aber solche 
Konstruktionen mit Mischmasch aus Artithmetik und Logig sind äusserst 
unübersichtlich ... Ein ~1UL hätte es auch getan.

Und wir wissen ja auch nicht was der Verfasser wirklich gewollt hat.

von Mark B. (markbrandis)


Lesenswert?

Frank M. schrieb:
> Mark B. schrieb:
>> Man muss schon ziemlich blind sein oder ein völlig unfähiger
>> Programmier, um den hier gezeigten Code in irgend einer Weise als
>> sinnvoll zu bezeichnen.
>
> Es ging nicht um die Sinnigkeit/Unsinnigkeit.

Wer sagt das?

Wenn Du in einem Code Review sitzt und eine völlig unsinnige Funktion 
entdeckst, sprichst Du dann über die Details der Implementierung? Oder 
sagst Du: "Diese Funktion ergibt so keinen Sinn. Bitte wegschmeißen und 
neu schreiben."

von Mark B. (markbrandis)


Lesenswert?

Hans-Georg L. schrieb:
> Und wir wissen ja auch nicht was der Verfasser wirklich gewollt hat.

Das ist richtig. Wenn es ihm aber nur um die bitweise Negation gegangen 
wäre, wäre es freilich intelligent gewesen auch nur diese Codezeile 
hinzuschreiben.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Mark B. schrieb:
> Wenn Du in einem Code Review sitzt und eine völlig unsinnige Funktion
> entdeckst, sprichst Du dann über die Details der Implementierung?

Es war offensichtlich, dass die Funktion nur in Auszügen abgebildet 
wurde. Das kann man unter Einsatz des Verstandes leicht erkennen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Mark B. schrieb:
> Das ist richtig. Wenn es ihm aber nur um die bitweise Negation gegangen
> wäre, wäre es freilich intelligent gewesen auch nur diese Codezeile
> hinzuschreiben.

Er hat den Funktionskopf hingeschrieben, um die Typen der verwendeten 
Variablen anzuzeigen. Ohne diese Typdefinitionen wäre eine einzelne 
Zeile ziemlich unsinnig, oder?

von Mark B. (markbrandis)


Lesenswert?

Frank M. schrieb:
> Mark B. schrieb:
>> Wenn Du in einem Code Review sitzt und eine völlig unsinnige Funktion
>> entdeckst, sprichst Du dann über die Details der Implementierung?
>
> Es war offensichtlich, dass die Funktion nur in Auszügen abgebildet
> wurde.

Woraus schließt Du das? Der Themenersteller macht hierzu keine weiteren 
Angaben.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Mark B. schrieb:
> Woraus schließt Du das?

Kleinhirn an Großhirn:

 "Was soll diese Funktion? Diese ist unsinnig"

Großhirn an Kleinhirn:

 "Möglichkeit 1: Der User ist dumm und kann kein C"
 "Möglichkeit 2: Der User ist intelligient und reduziert den Code
  auf das Wesentliche"

Kleinhirn an Großhirn:

 "Dann hätte auch eine einzelne Zeile gereicht"

Großhirn an Kleinhirn:

 "Dann wären die Typen der Variablen (long oder int) nicht klar gewesen"

Ich habe mich für die Intelligenz des Users entschieden, Du für die 
Dummheit desselben.

von Mark B. (markbrandis)


Lesenswert?

Frank M. schrieb:
> Mark B. schrieb:
>> Woraus schließt Du das?
>
> Kleinhirn an Großhirn:
>
>  "Was soll diese Funktion? Diese ist unsinnig"
>
> Großhirn an Kleinhirn:
>
>  "Möglichkeit 1: Der User ist dumm und kann kein C"

Er hast selbst gesagt, dass seine C-Kenntnisse eingerostet sind. Und 
Dinge wie Bits setzen, Bits löschen und Bits negieren sind jetzt nicht 
unbedingt das, was ich als fortgeschrittene Themen in der 
C-Programmierung ansehen würde.

Edit:
Um diese Frage hier zu beantworten:

> und wofür könnte es gut sein in der Funktion?

sollte man dann schon die komplette Funktion vorliegen haben. Nicht 
anwesende Code-Teile zu raten ist immer schwierig ;-)

von testen (Gast)


Lesenswert?

Ralf schrieb:
> ulNewPosition &= (unsigned long)(~1);


bit0 in ulNewPosition wird gelöscht.

>
>   ucMotor &= 1;

ucMotor wird auf 1 gesetzt, sofern bit0 in ucMotor 1 ist.

von Cprog (Gast)


Lesenswert?

>ucMotor wird auf 1 gesetzt, sofern bit0 in ucMotor 1 ist.
Naja.

Es werden alle Bits von ucMotor auf Null gesetzt. Nur das LSB (unterste 
Bit) bleibt auf 1 wenn es vorher schon 1 war.

von Dieter F. (Gast)


Lesenswert?

Frank M. schrieb:
> Großhirn an Kleinhirn:
>
>  "Möglichkeit 1: Der User ist dumm und kann kein C"
>  "Möglichkeit 2: Der User ist intelligient und reduziert den Code
>   auf das Wesentliche"

"Möglichkeit 3: Der User Ralf (der sich nicht weiter gemeldet hat,) 
veralbert alle

von Rolf M. (rmagnus)


Lesenswert?

Frank M. schrieb:
> Mark B. schrieb:
>> Wenn Du in einem Code Review sitzt und eine völlig unsinnige Funktion
>> entdeckst, sprichst Du dann über die Details der Implementierung?
>
> Es war offensichtlich, dass die Funktion nur in Auszügen abgebildet
> wurde. Das kann man unter Einsatz des Verstandes leicht erkennen.

Die Überschrift heißt "C-Funktion verstehen", und dann wird eine 
C-Funktion hingeschrieben, die in ihrer so hingeschriebenen Gesamtheit 
keinen Sinn ergibt. Da finde ich nicht so offensichtlich, dass die 
Funktion an sich gar keine Relevanz haben soll.

Frank M. schrieb:
> Ich habe mich für die Intelligenz des Users entschieden, Du für die
> Dummheit desselben.

Intelligent ist, echten Code hinzuschreiben oder wenigstens Änderungen 
gegenüber diesem als solche zu markieren. Dann kann man sich viel 
Diskussion sparen.

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.