:1 in C/C++

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

:1 in C/C++

Beitrag von Mathias »

Ich habe schon wieder so was lustiges in C/C++ entdeckt:

Code: Alles auswählen

typedef struct{
  Uint32 hw_available:1;
  Uint32 wm_available:1;
  Uint32 blit_hw:1;
  Uint32 blit_hw_CC:1;
  Uint32 blit_hw_A:1;
  Uint32 blit_sw:1;
  Uint32 blit_sw_CC:1;
  Uint32 blit_sw_A:1;
  Uint32 blit_fill;
  Uint32 video_mem;
  SDL_PixelFormat *vfmt;
} SDL_VideoInfo;
Was bedeutet das ":1" ?
Ist das in Pascal das gleiche wie dies ?

Code: Alles auswählen

type
  TTest= record
    r:1..2;
    g:1..2;
    b:1..2;
  end;
begin
  WriteLn(SizeOf(TTest));  // --> 3
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1910
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: :1 in C/C++

Beitrag von Warf »

Nicht ganz, zum einen muss der Record bitpacked sein, zum adneren muss die range 0 basiert sein:

Code: Alles auswählen

  TTest = bitpacked record
    a: 0..1;
    b: 0..1;
    c: 0..1;
    d: 0..1;
    e: 0..1;
    f: 0..1;
    g: 0..1;
    h: 0..1;
  end; -> Sizeof = 1 
Also als faustregen :n in C ist 0..(n^n-1) in pascal.

siro
Beiträge: 732
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: :1 in C/C++

Beitrag von siro »

Das Original in C
hier wird hinter dem Doppelpunkt die Anzahl der Bits angegeben:
Also z.B. 4 Bits für die Revision, da passen also die Zahlen 0..15 rein
oder PartNo belegt 12 Bits. Da passen die Zahlen 0..4095 rein

Code: Alles auswählen

typedef volatile union
{
  struct
  {
    U32 Revision    :  4;   // [0..3] Revision nunber, the p value in the rnpn product revision identifier 0x0 = r2p0
    U32 PartNo      : 12;   // Part number of the processor: 0x23 = Cortex-M3
    U32 Constant    :  4;   // read as 0x0F
    U32 Variant     :  4;   // Variante number, the r value ist the rnpn product revision identifier
    U32 Implementer :  8;   // Implementer code: 0x41 = ARM
  } bits;
  U32 value;
} CPUID_TypeDef;

#define LPC_CPUID (*(CPUID_TypeDef *)(0xE000ED00))
---------------------------
In Pascal sieht es etwas anders aus, hier wird angegebn welcher Wertebereich da reinpassen soll
und der Compiler kümmert sich um die Anzahl und Belegung der Bits.

Um es etwas einfacher(übersichtlicher) zu machen habe ich die Typen mit den entsprechenden Bits definiert
z.B. T6Bit was in Pascal dann bedeutet Wertebereich 0..63

Code: Alles auswählen

// Das macht es etwas übersichtlicher....
Type T1Bit = 0..1;
     T2Bit = 0..3;
     T3Bit = 0..7;
     T4Bit = 0..15;
     T5Bit = 0..31;
     T6Bit = 0..63;
     T7Bit = 0..127;
     T8Bit = 0..255;
     T9Bit = 0..511;
     T10Bit = 0..1023;
     T11Bit = 0..2047;
     T12Bit = 0..4095;
//....usw.

// der Record sieht dann so aus:

Type CPUID_TypeDef = bitpacked record
  case boolean of
  true: (
    Revision    :  T4Bit;   // [0..3] Revision number, the p value in the rnpn product revision identifier 0x0 = r2p0
    PartNo      :  T12Bit;  // Part number of the processor: 0x23 = Cortex-M3
    Constant    :  T4Bit;   // read as 0x0F
    Variant     :  T4Bit;   // Variant number, the r value ist the rnpn product revision identifier
    Implementer :  T8Bit;   // Implementer code: 0x41 = ARM
    );
  false : ( value:UInt32);  // 32 Bit Wert
end;


// zum Testen habe ich eine Variable angelegt, sonst gibts nen Laufzeitfehler auf dem PC,
// hier darf ich ja nicht auf feste Adressen zugreifen.
var dummy:UInt32;
var LPC_CPUID : CPUID_TypeDef absolute dummy;    // var LPC_CPUID : CPUID_TypeDef absolute $E000ED00;

procedure TForm1.FormCreate(Sender: TObject);
begin
  LPC_CPUID.PartNo:=35;
  caption:=IntToStr(SizeOf(LPC_CPUID));   // ergibt 4, es werden 4 Bytes belegt
  caption:=IntToStr(LPC_CPUID.PartNo);    // ergibt 35, habe ich ja gesetzt
  caption:=IntToStr(LPC_CPUID.value);     // ergibt 560 weil (35 viermal links (Revision hat 4 Bits) schieben = 560)
end;                 
Man kann auf dieses Art und Weise direkt auf den 32 Bit Wert des Registers zugreifen oder aber auch auf enzelne Bits.
Hauptanwendung sind die Prozessor/Peripherie-Register des Microcontrollers.

Das ist also ein Variantenrecord mit eizelnen Bitzugriffen
Zuletzt geändert von siro am Sa 7. Jan 2023, 15:52, insgesamt 2-mal geändert.
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: :1 in C/C++

Beitrag von Mathias »

Nicht ganz, zum einen muss der Record bitpacked sein, zum adneren muss die range 0 basiert sein:
Ja, das bitpacked ist noch wichtig.
So wie es scheint, habe ich gerade ein Bug oder eine fehlende Implementation entdeckt.
C/C++ Original-Source:

Code: Alles auswählen

/** Useful for determining the video hardware capabilities */
typedef struct SDL_VideoInfo {
	Uint32 hw_available :1;	/**< Flag: Can you create hardware surfaces? */
	Uint32 wm_available :1;	/**< Flag: Can you talk to a window manager? */
	Uint32 UnusedBits1  :6;
	Uint32 UnusedBits2  :1;
	Uint32 blit_hw      :1;	/**< Flag: Accelerated blits HW --> HW */
	Uint32 blit_hw_CC   :1;	/**< Flag: Accelerated blits with Colorkey */
	Uint32 blit_hw_A    :1;	/**< Flag: Accelerated blits with Alpha */
	Uint32 blit_sw      :1;	/**< Flag: Accelerated blits SW --> HW */
	Uint32 blit_sw_CC   :1;	/**< Flag: Accelerated blits with Colorkey */
	Uint32 blit_sw_A    :1;	/**< Flag: Accelerated blits with Alpha */
	Uint32 blit_fill    :1;	/**< Flag: Accelerated color fill */
	Uint32 UnusedBits3  :16;
	Uint32 video_mem;	/**< The total amount of video memory (in K) */
	SDL_PixelFormat *vfmt;	/**< Value: The format of the video surface */
	int    current_w;	/**< Value: The current video mode width */
	int    current_h;	/**< Value: The current video mode height */
} SDL_VideoInfo;
FPC-Source:

Code: Alles auswählen

  // Useful for determining the video hardware capabilities
  PSDL_VideoInfo = ^TSDL_VideoInfo;
  TSDL_VideoInfo = record
    hw_available: UInt8; // Hardware and WindowManager flags in first 2 bits ( see below )
    {hw_available: 1; // Can you create hardware surfaces
    wm_available: 1; // Can you talk to a window manager?
    UnusedBits1: 6;}
    blit_hw: UInt8; // Blit Hardware flags. See below for which bits do what
    {UnusedBits2: 1;
    blit_hw: 1; // Flag:UInt32  Accelerated blits HW --> HW
    blit_hw_CC: 1; // Flag:UInt32  Accelerated blits with Colorkey
    blit_hw_A: 1; // Flag:UInt32  Accelerated blits with Alpha
    blit_sw: 1; // Flag:UInt32  Accelerated blits SW --> HW
    blit_sw_CC: 1; // Flag:UInt32  Accelerated blits with Colorkey
    blit_sw_A: 1; // Flag:UInt32  Accelerated blits with Alpha
    blit_fill: 1; // Flag:UInt32  Accelerated color fill}
    UnusedBits3: UInt8; // Unused at this point
    video_mem: UInt32; // The total amount of video memory (in K)
    vfmt: PSDL_PixelFormat; // Value: The format of the video surface
    current_w : SInt32;	// Value: The current video mode width
	  current_h : SInt32;	// Value: The current video mode height
  end; 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: :1 in C/C++

Beitrag von Mathias »

Ich habe es mal versucht den Pascal-Code zu korrigieren:

Code: Alles auswählen

type
  // Useful for determining the video hardware capabilities
  PSDL_VideoInfo2 = ^TSDL_VideoInfo2;
  TSDL_VideoInfo2 = bitpacked record
    //    hw_available: UInt8; // Hardware and WindowManager flags in first 2 bits ( see below )
    hw_available: 0..1; // Can you create hardware surfaces
    wm_available: 0..1; // Can you talk to a window manager?
    UnusedBits1: 0..63;
    //    blit_hw: UInt8; // Blit Hardware flags. See below for which bits do what
    UnusedBits2: 0..1;
    blit_hw: 0..1; // Flag:UInt32  Accelerated blits HW --> HW
    blit_hw_CC: 0..1; // Flag:UInt32  Accelerated blits with Colorkey
    blit_hw_A: 0..1; // Flag:UInt32  Accelerated blits with Alpha
    blit_sw: 0..1; // Flag:UInt32  Accelerated blits SW --> HW
    blit_sw_CC: 0..1; // Flag:UInt32  Accelerated blits with Colorkey
    blit_sw_A: 0..1; // Flag:UInt32  Accelerated blits with Alpha
    blit_fill: 0..1; // Flag:UInt32  Accelerated color fill}
    UnusedBits3: uint16; // Unused at this point
    video_mem: uint32; // The total amount of video memory (in K)
    vfmt: PSDL_PixelFormat; // Value: The format of the video surface
    current_w: SInt32;  // Value: The current video mode width
    current_h: SInt32;  // Value: The current video mode height
  end;       
Am besten vergleiche ich es mal mit einem C-Beispiel, ob hinten das gleiche raus kommt.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten