kategoria: ANSI C
[#1] Tablica o zerowym rozmiarze
W NDK dla systemu 3.2 w pliku Include_H/prefs/workbench.h są dwie struktury:

struct WorkbenchHiddenDevicePrefs
{
	UBYTE whdp_Name[0]; /* C String including NUL char */
};

/* New for V47 */

struct WorkbenchTitleFormatPrefs
{
    TEXT wtfp_Format[0];
};


Czy ktoś z C ekspertów mógłby wyjaśnić o co chodzi z tymi tablicami o zerowym rozmiarze?
W inkludach dla ASMa to samo jest napisane tak:

STRUCTURE WorkbenchHiddenDevicePrefs,0
	UBYTE	whdp_Name			; first char of C String including NULL char
    LABEL WorkbenchHiddenDevicePrefs_SIZEOF

;---------------------------------------------------------------------------

/* New for V46 */

;---------------------------------------------------------------------------

    STRUCTURE WorkbenchTitleFormatPrefs,0
	UBYTE	wtfp_Name			; first char of C String including NULL char
    LABEL WorkbenchTitleFormatPrefs_SIZEOF


Pomijając burdel w komentarzach (struktura WorkbenchTitleFormatPrefs jest w końcu od v46 czy v47? ;) )
to patrząc na kod asemblerowy, to zapis C:
UBYTE whdp_Name[0];

moża zapisac po prostu jako:
UBYTE whdp_Name;

dobrze rozumiem?
Jeśli tak to po co deklaracja zerowej tablicy, to troche wbrew logice, w E np w ogóle nie da się zadeklarować takiej tablicy. Chyba że ma to jakiś głębszy cel?
[#2] Re: Tablica o zerowym rozmiarze

@vojo, post #1

Na tym forum jest z pewnością więcej lepszych ode mnie, ale jeśli chcesz znać moją skromną opinię to dla mnie to wygląda jak próba zostawienia "na później", tak, że w miarę rozbudowania w przyszłości może nie być zerowa.
[#3] Re: Tablica o zerowym rozmiarze

@vojo, post #1

Tak samo jak: char* == char[]
Czyli wydaje mi się że można:
UBYTE* whdp_Name;
zamiast:
UBYTE whdp_Name[0];
[#4] Re: Tablica o zerowym rozmiarze

@BigBang, post #3

Tylko ze zapis w inkludze ASM sugeruje ze sizeof tych struktur to 1 bajt, a jak tam dasz wskaźnik to od razu masz 4 bajty.
[#5] Re: Tablica o zerowym rozmiarze

@vojo, post #4

Racja, w strukturze występuje tablica, ale rozmiar deklarowany ma zero (jeśli nie jest to wskaźnik to struktura musi mieć podaną długość tablicy składowej). Ciekawe co to za cudo i jaki to ma sens - sprawdzę jak to się kompiluje na gcc.
[#6] Re: Tablica o zerowym rozmiarze

@vojo, post #1

Tablica o zerowym rozmiarze jako element struktury jest sposobem zadeklarowania na końcu tej struktury bufora na dane o nieokreślonej długości. Bufor musi być samoopisujący się, czyli z jego treści musi wynikać faktyczna długość. Typowym przykładem jest łańcuch tekstowy zakończony zerem, albo taglista. Przy takiej deklaracji możemy używać nazwy tablicy jako wskaźnik na bufor.

Tego typu struktury alokuje się dynamicznie, jawnie dodając rozmiar potrzebnego bufora do rozmiaru struktury. Najwygodniej używać funkcji pamiętających rozmiar alokacji (np. AllocVec), żeby nie trzeba było pamiętać ile my tego bufora tam właściwie dorzuciliśmy.
2
[#7] Re: Tablica o zerowym rozmiarze

@Krashan, post #6

Ok, dzięki, już rozumiem ideę takiej tablicy, chociaż wydaje mi się to niepotrzebną komplikacją że strony developera,
bo jeśli w tym buforze ma być string (sądząc po komentarzach w plikach naglowkowych), to dużo czytelniejszy byłby zwykły wskaźnik na char.

Dodatkowe zaciemnianie poprzez różne typy na to samo, raz UBYTE, a za chwilę TEXT. Nawet w nazewnictwie pól widać niedbałość, w strukturze WorkbenchTitleFormatPrefs w inkludzie C jest format, w inkludze ASM to samo pole nazywa się name.
[#8] Re: Tablica o zerowym rozmiarze

@vojo, post #7

Ok, dzięki, już rozumiem ideę takiej tablicy, chociaż wydaje mi się to niepotrzebną komplikacją że strony developera, bo jeśli w tym buforze ma być string (sądząc po komentarzach w plikach naglowkowych), to dużo czytelniejszy byłby zwykły wskaźnik na char.
To nie jest niepotrzebna komplikacja, bo dzięki temu oszczędzasz 4 bajty (jakie zająłby wskaźnik), jedno adresowanie pośrednie (przy każdym dostępie) i jedną alokację pamięci. Jeżeli wielkość bufora jest znana w momencie alokacji struktury i nie zmienia się aż do dealokacji, to dobre rozwiązanie.

Ostatnia aktualizacja: 28.07.2021 13:03:17 przez Krashan
2
[#9] Re: Tablica o zerowym rozmiarze

@Krashan, post #8


To nie jest niepotrzebna komplikacja, bo dzięki temu oszczędzasz 4 bajty (jakie zająłby wskaźnik), jedno adresowanie pośrednie (przy każdym dostępie) i jedną alokację pamięci. Jeżeli wielkość bufora jest znana w momencie alokacji struktury i nie zmienia się aż do dealokacji, to dobre rozwiązanie.


Ok, technicznie może to się broni, chociaz uważam czytelność kodu jest ważniejsza niż te kilka bajtów pamięci. Zerowy rozmiar tablicy jest nieintuicyjny, i jak sam napisałeś żeby to działało dobrze to musi zaistnieć kilka warunków (znany z góry rozmiar bufora i jego niezmienność), które nie wynikają wprost z deklaracji tablicy.
Jeszcze gdyby to było w jakieś strukturze która mogłaby np w jakiejś pętli zaistnieć, to ok, oszczędności mogłyby mieć sens, ale w tym przypadku raczej to nie zachodzi.

Commodore na to nie wpadło, dopiero NDK z Hyperiona ma takie konstrukcje.

No ale skoro jest to zgodne ze sztuką, to już się nie czepiam, poza tym nie jestem obiektywny jeśli chodzi o C:)
[#10] Re: Tablica o zerowym rozmiarze

@vojo, post #9

Commodore na to nie wpadło
Oczywiście, że wpadło, podobne konstrukcje w systemie trafiają się dość często, chociaż nie zawsze w publicznym API. No a gdy się trzeba zmieścić w ROM-ie, to te kilka bajtów jest ważniejsze niż czytelność kodu. Zbędne zaś alokacje pamięci szkodzą zawsze, zwłaszcza w standardowym systemowym alokatorze.
[#11] Re: Tablica o zerowym rozmiarze

@vojo, post #9

To chodzi bardziej o to ze ten string jest dokladnie za koncem struktury a nie pod jakims innym adresem.
Czesto robi sie tak aby przekazac jakis bufor zawierajacy na poczatku strukture a za nim od razu string (lub inny obszar o zmiennej dlugosci). Daje to oszczednosc na licznie allokacji oraz brak ryzyka ze pointer wskazywalby w zly obszar pamieci. Generalnie bezpieczne API powinno unikac przekazywania pointerow jako danych, ale to juz inny temat.
Jednoczesnie mozna dostepowac do stringa po nazwie elementu struktury, zamiast liczac offset, co poprawia czytelnosc kodu.
W kompilatorach ktore nie lubia tablic o rozmiarze 0 uzywa sie tablic o rozmiarze 1, np. przez #define ANYSIZE_ARRAY 1; Wydaje mi sie tez ze tablica o rozmiarze 0 powinna miec rozmiar 0, przy upakowanej strukturze, co pozwala miec puste dane, czyli oszczednosc 4B w stosunku do pointera, ale to moze zalezec od platformy.
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem