2015-05-10 17 views
9

Chcę zmusić ciągi mają zostać przydzielone do lokalnych zmiennych dynamicznie w czasie wykonywania przez instrukcją montażu bez ciąg zajmując pamięci w sekcji danych (takich jak tylko do odczytu sekcji danych).C++ gcc ciąg inline

następuje wydaje się doskonale działa:

char foo[] = "bar"; 

Kod montaż staje:

movl $7496034, 40(%esp) 

Zatem foo inicjowany jest "bar" pośrednictwem instrukcji w czasie wykonywania movl.

Jak mogę wymusić to na wszystkich operacjach ciągami?

Na przykład, jeśli mijam ciąg dosłownego do funkcji:

testfunc("bar"); 

Ciąg "bar" zostaną przydzielone w sekcji w tym przypadku.

+1

'char foo [] =" bar "; testfunc (foo); 'nie działa? –

+7

Jestem ciekawy, jakie są tego powody. –

+0

@Andrew: to zmusi mnie do zadeklarowania zmiennej za każdym razem, co staram się uniknąć. – user3575889

Odpowiedz

5

Pokazana technika działa tylko w specjalnym przypadku. Zasadniczo kompilator może umieszczać zawartość ciągów w sekcji. Na przykład przy tej małej korekcie:

char foo[] = "bar\0"; 

Łańcuch pojawi się teraz w sekcji danych tylko do odczytu.

Wiedząc, że technika nie zawsze działa, możesz użyć makra, aby zautomatyzować technikę, aby móc przekazywać ciągi do funkcji bez użycia wskaźników do sekcji tylko do odczytu.

#define string_invoke(Func, Str)  \ 
     []() -> decltype(Func(NULL)) { \ 
      char foo[] = Str;   \ 
      return Func(foo);   \ 
     }() 
+0

Jakiego rodzaju "sekcji" myślisz, o czym op mówi? –

+0

@ DOUGLASO.MOEN: Prawdopodobnie sekcja "rodata", jeśli ELF. Kompilator ma optymalizację, aby zamienić ciągi znaków w literały numeryczne i odpowiednio je zainicjować. Pokazałem, że optymalizacja nie zawsze ma miejsce, a inicjalizacja jest "memcpy" z 'rodata'. – jxh

3

Masz ciąg czterech znaków, które chcesz zainicjować z czterech znaków („bar” plus null-terminator.) Kompilator rozpoznaje możliwość niesamowite mikro optymalizacji i oszczędza całkowitą cztery bajty w łańcuch, który ma taki sam wzór bitowy jak "bar". Na komputerach 64-bitowych kompilator może również używać tej techniki do ciągów o długości 8 znaków. Wspaniale! Ale nie oczekuj, że ta optymalizacja będzie obowiązywać wszędzie tam, gdzie używasz ciągów C.

Gdy funkcja przyjmuje na przykład łańcuch C jako parametr, oczekuje wskaźnika na tablicę, a nie na liczbę całkowitą.

Zniekształcenie kodu w celu wymuszenia optymalizacji konkretnego kompilatora jest świetnym sposobem na napisanie nieosiągalnego, łamliwego kodu. Lepiej napisać jasny kod przy użyciu wydajnych algorytmów i cieszyć się każdą niesamowitą optymalizacją, którą może zastosować kompilator.

+0

Dobre wyjaśnienie, dlaczego należy unikać takiej bezużytecznej optymalizacji strony programistycznej. – g24l

+2

Przykro mi, ale to nie jest wiarygodna odpowiedź. Mówisz "moc" i nie cytujesz źródła. Szukamy wyjaśnienia tego zachowania GCC, co go wyzwala. –

+0

Nie próbuję być autorytatywny. Powiedziałem, że GCC "może" użyć tej samej optymalizacji, ponieważ jest to teoretycznie możliwe, ale nie sprawdziłem ani nie dbałem o to. Wyjaśniłem zachowanie GCC, a następnie powiedziałem nie wymuszaj swojego stylu kodowania, aby spróbować wywołać tę optymalizację. – RichN