[gcc] Moje strcpy vs biblioteczne strcpy

0

Witam.
Napisałem własną funkcję strcpy gdyż po skompilowaniu program zajmuje ok 1kb mniej.
Jest to spora różnica gdyż dla mnie cenny jest każdy bajt(programuję procesorki).
Zrobiłem sobie 2 pliki:

sstring.h

#ifndef __SSTRING_H__
#define __SSTRING_H__
  int dlen(unsigned int val);
  int strlen(char * val);
  int atoi(char * val);
  int itoa(char * dst, unsigned int src);
  void strcpy(char * dst, char * src);
#endif

sstring.c(frag)

//...//
void strcpy(char * dst, char * src){
  while(*dst = *src){
	dst++;
	src++;
  }
}
//...//

Wszystko ładnie się kompiluje tylko dostaje warninga:

./include/sstring.h:7: warning: conflicting types for built-in function 'strcpy'

Gdy wywale funkcje strcpy i prototyp, na jego miejsce wchodzi strcpy z pakietu gcc(i plik wynikowy więcej zajmuje), chociaż nigdzie nie includuje żadnych bibliotek itp(tylko własne).
Zdaje mi się że te strcpy siedzi już w tym kompilatorze i po odczytaniu prototypu mojego strcpy odnosi się do tego strcpy gcc'owego.
Co na to poradzić? Da się jakoś zrobić undef "systemowego" strcpy?

0

Raczej nic na to nie poradzisz, jedyne co mozesz to taka sztuczka:

#define strcpy _strcpy

Wpisz to na poczatku pliku sstring.h. W takim wypadku de facto nie deklarujesz strcpy, tylko _strcpy, ale #define przysloni deklaracje funkcji bibliotecznej i mozesz uzywac po prostu strcpy.

0

Może to nie jest odpowiedź na pytanie, ale jakoś nie mogłem się powstrzymać,

Powyższy kod można skrócił i "upiększyć" do:

void strcpy(char* dst, char* src){
  while(*dst++ = *src++);
}
0

Dziwny motyw z tym rozmiarem?
Jak przeczytałem początek to byłem przekonany, że kompletnie zrezygnowałeś z biblioteki string.h i napisałeś swoje wersje potrzebnych funkcji. W takim przypadku jest dla mnie zrozumiałe czemu oszczędziłeś 1kB.
Dalej piszesz, że masz konflikt ze starą biblioteką to to już dla mnie wielka tajemnica. Jakim cudem oszczędziłeś pamięć pozostawiając bibliotekę i równocześnie dopisując nowe metody? Wyjaśni mi to pls!

Moje rady: wywal bibliotekę standardową string.h jeśli nie masz zamiaru z niej korzystać (nie zapomnij o string.lib).

0

Co do konfliktu nazw - są namespace'y. Możesz wrzucić swoje funkcje do własnego namespace'a, lub zostawić je w globalnym namespace'u, a includować <cstring>, wtedy oryginalny strcpy będzie w przestrzeni nazw std.

Poza tym słyszałem że są kompilatory c++ dedykowane właśnie małym procesorkom, może warto by coś takiego poszukać.

0
adf88 napisał(a)

Co do konfliktu nazw - są namespace'y. Możesz wrzucić swoje funkcje do własnego namespace'a, lub zostawić je w globalnym namespace'u, a includować <cstring>, wtedy oryginalny strcpy będzie w przestrzeni nazw std.

Poza tym słyszałem że są kompilatory c++ dedykowane właśnie małym procesorkom, może warto by coś takiego poszukać.

A i owszem, jeśli się nie mylę to gcc się do nich zalicza.

0

Tylko, że namespace'y są w C++, w C, jak wiadomo, nie.

lub zostawić je w globalnym namespace'u, a includować <cstring>, wtedy oryginalny strcpy będzie w przestrzeni nazw std.

Hmm? Dlaczego? Chyba, że nie zrozumiałem.

0

Dawno państwo nie pisaliście w czysciutkim C, przecież tam include'y NIE MAJĄ ZNACZENIA! bez żadnych include można korzystać z funkcji std liba i linker je odnajduje. W starych kompilatorach w dodatku nie patrząc na typy argumentów, a jedynie na nazwę (bo typy argumentów nie są zapisane przecież w plikach lib, a, obj, o).

dlatego można było zrobić tak:
strcpy('x', 10.0 / 7)
i stary kompilator to puszczał, linker puszczał, a w programie się sypała ramka stosu czy coś-tam, bo strcpy było traktowane, jakby miał sygnaturę:
int strcpy(char, double);

w nowych gcc w celach bezpieczeństwa sygnatury są sprawdzane na etapie kompilacji i gcc rzuca warningami radośnie, a nawet błąd potrafi rzucić, wyświetlający dokładną deklarację funkcji, mimo, że (jeszcze raz) żadnego include nie ma.

czegoś takiego jak string.lib zwyczajnie nie ma, na pewno w gcc jest funkcja prosząca o ignorowanie całej biblioteki libc, ale tobie to niepotrzebne zapewne.

A na końcu może odpowiem na pytanie ;)
warning nie wynika z samego przysłonięcia, ale z przysłonięcia w zły sposób - sygnatury się nie zgadzają. w libc strcpy ma taką deklarację:

char* strcpy(char* to, const char *from);

i takiej samej użyj. Dodam, że u mnie test na dwóch plikach wykazał, że faktycznie przesłaniam to standardowe strcpy.

char* strcpy(char* to, const char *from) { return 0; }

int main() {
    char dst[10];
    strcpy(dst, "xxx");
    }
int main() {
    char dst[10];
    strcpy(dst, "xxx");
    }

po kompilacji do asemblera widać, że moje strcpy jest użyte, widać również, że plik exe z moim strcpy jest mniejszy (nie dziwota, już mniejszą funkcję trudno napisać ;) )

0

Twoje wyjaśnienie podoba mis się bardzo. Ale ma kilka słabości:

  1. strcpy nie jest częścią stdlib więc nie jest domyślnie inkludowany
  2. od biblioteki oczekiwałbym optymalnych funkcji czasami wykonanych w językach niskopoziomowych (assembler). Wywołania funkcji napisanej przez Pawells i tej z biblioteki ma niewielki i zawsze ten sam rozmiar. Tak proste funkcje mają rozmiar rzędu 20-30 bajtów (maks), więc skąd różnica aż 1kB?

Zastanawiając się dokładniej doszedłem do wniosku, że różnica aż 1kB musi być wynikiem potraktowania bibliotecznej strcpy jak funkcji inline.
Przyjrzałem się troszkę nagłówkowi string.h i widzę tam parę opcji szczególnych dla gcc. Przypuszczanie jest to zestaw makr i słów kluczowych, które w zależności od ustawień kompilatora (optymalizacji) powodują inne zachowanie funkcji strcpy (inline lub nie). To by sugerowało, że należy pogrzebać w ustawieniach kompilatora i włączyć optymalizację rozmiaru. Pisanie nowej funkcji byłoby bezcelowe (jeśli mam rację).

0

Cóż MarekR22, to może ja jeszcze raz napiszę odnośnie 1, że w języku C nagłówki nie muszą być includowane. Dodam, że ze swoimi funkcjami też możesz zrobić tak, że w jednym pliku C jest:
void moja_funkcja(double, double) { bla bla bla }
a w drugim nie ma deklaracji, include ani niczego innego, jest call:
moja_funkcja(44, 44);
(ten call spowoduje wysypanie ramki właśnie).
moja_funkcja(44., 44.);
(a taki już nie powinien)

a tak poza tym, to strcpy jest zdaje się częścią libc, więc na etapie linkowania jest wsadzony. Ponieważ podczas linkowania dajesz wszystkie swoje .obj, to odwołanie do moja_funkcja jest też wsadzane, itd itd. Z tego co pamiętam, to matematyczna biblioteka jest tylko oddzielnie, i używając np sqrt trzeba dodać -lmath, bo się linker wysypie. Ale jak już się poda -lmath to deklaracje znowu nie są potrzebne.

Co do gcc, to myślę, że w nowszych wersjach jest po prostu jakiś dodatkowy mechanizm poza includowaniem i linkowaniem, ponieważ nawet w C++ wywołanie funkcji np memset bez żadnych include jest możliwe, i leci warning mówiący coś o wywołaniu niezadeklarowanej builtin function (a przecież error powinien być jak w pysk strzelił).

A co do drugiego to, w sumie racja święta, bo nawet u mnie, gdzie oszczędność powinna być skrajna, zysk wynosi 140 bajtów. Ja się skoncentrowałem na tym, jak ta menda w C linkuje stdliba, i czy da się zastąpić prosto funkcje biblioteczne. Nad sensem się nie zastanawiałem, dobrze że czuwasz ;)

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