Typy uint i przedrostki

0

Mam pytanie dotyczące zasad dobrego programowania. Po pierwsze jak definiować poprawnie typ uint32? Jeżeli int i long ma taką samą długość (np. 32 bity), powinienem użyć

typedef unsigned long uint32

czy

typedef unsigned int uint32

Druga sprawa, czy dobrą praktyką jest przy zapisywaniu wartości do zmiennej używanie przyrostków (U, UL) i warto się tego trzymać?

1

Metod nazewnictwa zmiennych, funkcji, typów, klas itp... w programowaniu jest bardzo wiele. Są na ten temat całe książki ale także znajdziesz sporo materiałów w internecie.
Sam język nie narzuca żadnych zasad. W praktyce zupełnie inne zasady przyjmuje się w środowisku ludzi, którzy piszą kod w c/c++ na mikrokontrolery a inne podczas kodowania logiki biznesowej. Także niektóre firmy trzymają się popularnych standardów a inne tworzą własne konwencje nazewnictwa.
Ostatecznie ważne jest to żeby w ramach jednego projektu lub grupy projektów ze sobą powiązanych być konsekwentnym i stosować jeną metodologię. Przyjąć jedną z popularnych i nie wymyślać własnych "kulfonów".

6
  1. Typy już są zdefiniowane, nieco inaczej się piszą
    https://stackoverflow.com/questions/6013245/are-types-like-uint32-int32-uint64-int64-defined-in-any-stdlib-header

Dodatkowe ich zmapowanie sądzę nie będzie pomagało w niczym

  1. Literki wskazujące na typ zmiennej to dość archaiczna rzecz. Potrafię sobie przypomnieć takowe w Win32 API, tam miały częściowe uzasadnienie. Współcześnie mogą mieć sens w pisaniu kodu na mikrokontrolery (i podobne urządzenia, hardware), ale nie bardzo widzę inne zastosowanie.

Używa się nazw mających znaczenie merytoryczne, np (PL) suma/ (EN) sum.
Po drugie staramy się deklarować zmienne w jak najbardziej wewnętrznym zakresie, jednym z efektów jest to, że wzrok ma blisko deklarację i użycie.

5
  1. Nie masz absolutnie żadnej gwarancji, że ani unsigned long, ani unsigned int będą 32-bitowe — standard mówi jedynie, że ten pierwszy musi być co najmniej 32-bitowy (i na LP64 będzie 64-bitowy), a ten drugi co najmniej 16-bitowy (co na LP32 da mu 16 bitów). Jeśli chcesz mieć inta o gwarantowanej długości, użyj uint32_tcstdint.
  2. Kwestia stylu. Nie zaszkodzi Ci, może polepszyć czytelność, może być uznana za niepotrzebne śmieci. Osobiście tego nie robię, ale zacząłbym, gdybym pisał kiedyś kod, w którym rozmiar zmiennych i tego typu szczegóły techniczne zaczynają mieć fundamentalne znaczenie.
0

Pracuję z oprogramowaniem pod systemy wbudowane i w projekcie są używane typy zdefiniowane w sposób, jaki podałem w pierwszym poście , stąd moje pytanie :). Natomiast zauważyłem, że stosowane są też przyrostki określające typ zmiennej, ale nie jest to zasada, której programiści sztywno się trzymają, stąd moje pytanie, czy to tylko kwestia dobrych manier w pisaniu kodu, czy może mieć kluczowe znaczenie w jakichś szczególnych przypadkach?

2

W dobie nowoczesnych IDE notacja węgierska chyba tylko przeszkadza

vUsing adjHungarian nnotation vmakes nreading ncode adjdifficult.

PS:

czy to tylko kwestia dobrych manier

Jesli antypattern nazywasz dobrymi manierami...

https://softwareengineering.stackexchange.com/questions/102689/what-is-the-benefit-of-not-using-hungarian-notation

0

Mówię o przyrostkach unsigned, unsigned long, np.

unsigned long var = 0xFFFFUL
0

A nie, no to już jest zupełnie inna bajka. Ja to w ogóle myślałem, że Ci chodzi o pisanie np. unsigned long long variable = 123456ull zamiast unsigned long long variable = 123456; koledzy że o notacji węgierskiej, czyli unsigned long long variable_ull = 123456

W każdym razie, unsigned long to jest coś zupełnie innego niż long, więc to różnica semantyczna, nie tylko estetyczna jak wyżej.

EDYCJA: a, czyli jednak Ci chodziło o to, co na początku myślałem, że Ci chodziło…

0

Najbezpieczniej tak:


    #include <iostream>
    #include <cstdint>
    using namespace std;
     
    typedef uint32_t uint32;
     
    int main() {
    	uint32 liczba = 123u;
    	cout << "Liczba: " << liczba << endl;
    	return 0;
    }

https://ideone.com/zevCHB

W inny sposób generowanie typów o określonej długości może być bardzo pracochłonne jeśli ma być przenośne.

2

To nie lepiej od razu z stdint korzystac?

https://en.cppreference.com/w/cpp/header/cstdint

Edit: W sensie po co skracac o ten '_t'?

0
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;

uint8 var1 = 10U;
uint16 var2 = 10;
uint32 var3 = 10UL;

Czy przyrostki w literałach powyżej są użyte poprawnie?

EDIT: Czy w ogóle ma sens używanie przyrostków w literałach? Czy raczej definiując makro lub np. podczas porównywania zmiennej z liczbą?

if(var3 < 15UL)
2

Ale te typedefy to sa do d**y no..
stdint Ci daje typy za darmo

0

Kwestia użycia tego w projekcie, w którym pracuję :) to nie jest mój wymysł... teraz mi chodzi o kwestię, jak poprawnie operować na tak zdefiniowanych typach.

1

Nie rozumiem... W projekcie nie potrafia zainkludowac headera?
Przeciez long ma 4 LUB 8 bajtow... (Okey, powiedzmy ze kontrakt dla uint32 spelnia :D )

0

Ale chodzi o nazwe czy o typedefy? Przeciez to nie problem przealiasowac jak juz formalnosci wymagaja bez _t

Edit: ale wez mi tak nie kasuj postow... Cos o AUTOSAR mowiles?

1

AUTOSAR wymaga mapowania na typy ANSI C
https://www.autosar.org/fileadmin/user_upload/standards/classic/4-3/AUTOSAR_SWS_PlatformTypes.pdf

EDIT: Tak, przepraszam, chciałem przeredagować post :)

2
rafcio100 napisał(a):
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;

uint8 var1 = 10U;
uint16 var2 = 10;
uint32 var3 = 10UL;

Czy przyrostki w literałach powyżej są użyte poprawnie?

EDIT: Czy w ogóle ma sens używanie przyrostków w literałach? Czy raczej definiując makro lub np. podczas porównywania zmiennej z liczbą?

if(var3 < 15UL)

„Poprawnie”, to znaczy? Skompiluje się, jest zgodne ze standardem, nawet Cię pewnie kompilator nie okrzyczy, jak nie ma ustawionych wybitnie wysokich flag ostrzeżeń. Ale U to przyrostek dla unsigned int lub unsigned long (być może też i dla unsigned long long, nie jestem pewien, czy któryś z nowych standardów C też to podjął), choć u Ciebie jest unsigned char — przy czym, z tego co wiem, nie ma przyrostków dla unsigned char; brak przyrostka to int lub long int (ew. long long int, patrz wyżej), choć u Ciebie to unsigned short — i znowu, dla short też chyba nie ma przyrostków; i dopiero UL jest użyte w 100% tak, jak ma być.

Ale pozostaje najważniejsze pytanie, po co to robisz? Kompilator sobie zrzutuje literał jak trzeba, on nie potrzebuje tych podpowiedzi, nie wprowadzają narzutu na wykonanie kodu, a narzut na kompilację, jeśli w ogóle jest, to znacząco mniejszy, niż nawet czas na naciśnięcie pojedynczego klawisza; one są dla ludzi — więc musisz się zastanowić Ty i Twoi współpracownicy, co Wam to właściwie podpowiada? Czy faktycznie Wam jest lepiej z tym, czy może bez tego?

2

IMO burza w szklace wody.
Literały nie powinny znaleźć się bezpośrednio w kodzie, bo to jest zła praktyka zwana "Liczby magiczne".
Lekarstwem jest definiowanie stałych, które mają dobrze określony typ i nadanie im wartości za pomocą literału nie wymaga użycia suffix'ów oznaczających typ.

Wyjątkiem od liczb magicznych są wartości nie niosące ze sobą kontekstu np 0 1 2 (przykład: double s = a*t*t/2 + x0; - nikt normalny nie zastąpi 2 stałą).

Jedyny sens kiedy widzę sens używania suffix'ów do literałów:

  • użycie szablonów, gdzie trzeba narzucić konkretny typ, np auto a = std::min(0ll, x)
  • sufixy użytkownika (c++11):
using namespace std::literals;

auto duratiom = 5s;

1 użytkowników online, w tym zalogowanych: 0, gości: 1