Dzisiaj spotkałem się z wyjątkową osobowością, która, choć prawdopodobnie nie jest tak ważna, jest dla mnie zagadką. Może po prostu nie rozumiem poprawnie C++.Niejawne powiązanie wewnętrzne nie jest tym samym, co jawne powiązanie wewnętrzne ("statyczne")?
Niektóre tablice wewnątrz punktu źródłowego pliku napisowych, tak:
const char* a[] = { "a", "b", "c" };
const char* b[] = { "d", "e"};
const char* c[] = { "f", "g"};
Żaden z tych tablic wskaźnik jest zawsze wykorzystywane w żaden inny sposób niż były przekazywane do GetProcAddress
pobierać wskaźnik funkcji z biblioteki (jest to nieblokująca dynamiczna ładowarka funkcji OpenAL/EFX/capture i twórca/menedżer kontekstu).
W końcu przyszło mi do głowy, że powinienem zadeklarować te zmienne jako static const
, ponieważ nie są one potrzebne nigdzie poza tym plikiem .cpp, więc stworzenie wewnętrznego powiązania jawnego wydawało się odpowiednie. W każdym razie powinni oni mieć wewnętrzne powiązania (ISO14882 3.5 (3)), więc jesteśmy tylko dobrymi obywatelami, jasno określając, co kompilator już przyjmuje.
Dokonanie tej niewinnej zmiany spowodowało wzrost rozmiaru pliku wykonywalnego o 512 bajtów. Nie chodzi o dodatkowe 512b naprawdę ważne, ale po prostu nie wydawało się sensowne, że to samo spowoduje inny kod. Ponieważ static const
jest przestarzałe (ISO14882 7.3.1.1 (2)), próbowałem również anonimowego obszaru nazw, z tym samym wynikiem.
Patrząc na źródła asemblera pokazuje, że wyraźne powiązania wewnętrzne (static
lub namespace{}
) ruszy literały ciągów w .rdata
zamiast .data
oraz literały łańcuchowe są przeplatane z wskaźnik do łańcucha-dosłownych tablic, zamiast wszystko łańcuchy i wszystkie wskaźniki w jednym bloku, odpowiednio. W tym przypadku prawdopodobnie leży przyczyna różnej wielkości - bardzo prawdopodobne jest, że losowe przenoszenie danych z jednej sekcji do drugiej spowodowało ograniczenie rozmiaru sekcji. Co ciekawe, wszystkie 3 smaki zupełnie inaczej opisują nazwy.
Teraz zastanawiam się: czy popełniam błąd, czy te wskaźniki: , czy mają wewnętrzne powiązania?
Ponadto, w moim rozumieniu const
jest już tylko do odczytu, inhowfar jest static const
"więcej tylko do odczytu" (jeden przechodzi w .rdata
, a drugi nie)?
Och, oczywiście ... co za głupi, oczywisty błąd. Rzeczywiście, powinno to być 'const char * const a []', które również zachowuje się zgodnie z oczekiwaniami (niejawnie wewnętrzne powiązania i ma identyczne zniekształcanie). Ma również sens, dlaczego niestałe wskaźniki do literału byłyby w '.data', jeśli tablica nie jest stała. Po prostu literały, nie wiem ... Spodziewałbym się, że w każdym razie będą one tylko do odczytu. Nadal, doskonały połów. – Damon