Jak nazywać zmienne i funkcje w C.

0

Tworzę pewien projekt w C i chciałbym się trzymać jakiegoś standardy, aby kod był czytelny i żeby można było się pochwalić na rozwowie kwalifikacyjnej. Kiedyś pracowałem na jednym projekcie stworzonym na uczelni i wszystkie funkcje i zmienne były małymi literami napisane, jedynie define było dużymi.
np.

#define UART_BAUD_RATE 9600
int licznik = 0;
void com_send(char znak);

Zastanawiam się jak nazwać swoje funkcje:

uint8_t i2c_init(void);
uint8_t I2C_init(void);
uint8_t I2C_Init(void);

Który z tych trzech sposobów jest najbardziej w stylu C?
Jeśli funkcja inicjująca i2c wykona się poprawnie to powinna zwrócić 0 czy 1?

0

U siebie korzystam z tak zwanej notacji węgierskiej, nie wiem czy na pewno to się tak nazywa:

uint8_t i2cInit(void); 
void uartConfig(void);
int icounter;
class Communication{
};
const int MAX_LENGTH = 23;

Metody, funkcje od małej literki wraz z podziałem słów, wielką literą.
Własne typy od dużej litery.
Stałe, tak jak inni w projekcie, często tak samo jak typy, czyli z dużej.
Zmienne - wszystko małą.

Popatrz jak Ci wygodniej, jest wiele stylów pisania. Nie pamiętam dokładnie, ale chyba w książce "czysty kod", było kilka przykładów.

1
uint8_t i2c_init(void);

jest 'najbardziej poprawne' - zwracająca 0, gdy inicjalizacja się powiodła i numer błędu w przeciwnym razie (analogicznie jak na przykład samo main).

1

Notacja węgierska jest słaba. Zmienisz typ zmiennej i musisz nazwy wszystkich zmiennych zmieniać. A sprawdzić typ zmiennej to w IDE najechanie na zmienną, a w vim ctrl+]. Nadmiarowość informacji moim zdaniem.

Język C nie definiuje standardu kodowania, możesz pisać jak Ci się podoba. Osobiście nienawidzę łączenia camelCase z PascalCase i snake_case, i to jeszcze w jednym symbolu! UART_SendByte, a uart_send_byte. Może przy jednej definicji nie widać burdelu, ale czytać tak cały plik to oczy wypadają - ale to moja osobista opinia - ja wolę ALL_UPPER dla stałych oraz all_lower dla wszystkiego innego. Zwłaszcza, że wszystkie funkcje w libc są w takiej właśnie konwencji, no i ojcowie K&R też tak pisali:)

0

Jeśli funkcja inicjująca i2c wykona się poprawnie to powinna zwrócić 0 czy 1?

Jeśli ma zwracać tylko informację „poprawnie” albo „niepoprawnie”, to od tego jest bool.

#include <stdbool.h>

bool i2c_init(void)
{
    if (cośtam)
        return true;
    else
        return false;
}
0
Azarien napisał(a):

Jeśli ma zwracać tylko informację „poprawnie” albo „niepoprawnie”, to od tego jest bool.

a od kiedy w C masz typ bool?

jedyne co zawiera stdbool.h to

#define	false	0
#define	true	1
#define	bool	_Bool
typedef	int	_Bool;

niczym się nie różni od używania inta, zwykłe makra udające coś z innego języka - w C standardowo używa się intów do oznaczania rezultatów

1
Mały Młot napisał(a):
Azarien napisał(a):

Jeśli ma zwracać tylko informację „poprawnie” albo „niepoprawnie”, to od tego jest bool.

a od kiedy w C masz typ bool?

Od C99.

jedyne co zawiera stdbool.h to

#define	false	0
#define	true	1
#define	bool	_Bool
typedef	int	_Bool;

niczym się nie różni od używania inta, zwykłe makra udające coś z innego języka - w C standardowo używa się intów do oznaczania rezultatów

Właściwie to nie. _Bool jest natywnym typem i kompilator nie pozwoli aby w typie _Bool była wartość inna niż 0 lub 1. Gdy rzutujesz int na _Bool zostanie wygenerowany dodatkowy kod z test oraz setne.

I powiedz mi jeszcze, gdzie znalazłeś, że w stdbool.h jest typedef int _Bool;? Bo u mnie w systemie nie ma nic takiego (gcc 5.4.0).

0

niczym się nie różni od używania inta,

Różni się wiele. int służy do przechowywania liczb. bool służy do przechowywania wartości logicznej.

zwykłe makra udające coś z innego języka

To co pokazałeś to nagłówek dla przedpotopowych kompilatorów, symulujący prawdziwego boola za pomocą inta.
Prawdziwy bool (czy też _Bool) jest osobnym typem, a nie intem. Jest w standardzie C od 1999 roku. Od siedemnastu lat.

w C standardowo używa się intów do oznaczania rezultatów

Nie musimy w 2016 pisać tak jakby to był 1980.

0
mlyszczek napisał(a):

Notacja węgierska jest słaba. Zmienisz typ zmiennej i musisz nazwy wszystkich zmiennych zmieniać. A sprawdzić typ zmiennej to w IDE najechanie na zmienną, a w vim ctrl+]. Nadmiarowość informacji moim zdaniem.

Język C nie definiuje standardu kodowania, możesz pisać jak Ci się podoba. Osobiście nienawidzę łączenia camelCase z PascalCase i snake_case, i to jeszcze w jednym symbolu! UART_SendByte, a uart_send_byte. Może przy jednej definicji nie widać burdelu, ale czytać tak cały plik to oczy wypadają - ale to moja osobista opinia - ja wolę ALL_UPPER dla stałych oraz all_lower dla wszystkiego innego. Zwłaszcza, że wszystkie funkcje w libc są w takiej właśnie konwencji, no i ojcowie K&R też tak pisali:)

Chyba będę się trzymał tego co napisałeś.

A nazwy typów zdefiniowanych przez użytkownika jak wyglądają najepiej?

typedef enum
{
I2C_OK,
I2C_ERROR
}i2c_status_t;

typedef enum
{
I2C_OK,
I2C_ERROR
}I2C_status_t;

typedef enum
{
I2C_OK,
I2C_ERROR
}I2C_Status_T;
0

Tak jak Tobie się podobają:P Dla mnie jak wyżej, ALL_UPPER i all_lower. I naprawdę potrzebujesz tego typedefa na enuma? Nic to w sumie nie daje, oprócz tego, że nie piszesz enum nazwa, tylko nazwa przez co ograniczasz sobie przestrzeń nazw (dozwolone jest zrobienie np enum status status, co przy typedefie nie jest możliwe). Wciaż - jest to tylko moje zdanie i nie trzeba się z nim zgadzać. Dodatkowo _t jest zarezerwowane dla bibliotek systemowych i nie powinno się używać ich we własnym kodzie.

0

Nie rozumiem jeszcze dwóch rzeczy.
W jakim celu stosuje się następujące znaczniki:

#ifdef __cplusplus
 extern "C" {
#endif

//some code

#ifdef __cplusplus
}
#endif
 

Dlaczego przy zerowaniu bitu jest rzutowanie:

 
I2Cx->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ENPEC);
0

W jakim celu stosuje się następujące znaczniki:

Żeby ten sam nagłówek mógł zostać użyty pod C i pod C++ (mocno upraszczając).
Jeśli piszesz w C i nie interesuje cię C++ to nie zwracaj na to uwagi.

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