C-Funktion verstehen

Gast #4920596
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?
Gast #4920603
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.
Gast #4920609
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.
#4920638
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.
#4920725
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.
Moderator Persönliche Seite #4920780
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.
Moderator Persönliche Seite #4920789
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.
Gast #4920793
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.
#4920794
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".
#4920796
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.
#4920804
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.
#4920807
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."
Moderator Persönliche Seite #4920817
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?
Moderator Persönliche Seite #4920829
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.
#4920840
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 ;-)
#4922742
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren