2017-12-15 192 views
5

Myślę, że odpowiedź brzmi nie, i zazwyczaj nie mam problemu z przechodzeniem przez kod źródłowy, ale jestem trochę nowy w C/C++ i nie mogę znaleźć miejsca, gdzie ta stała jest zadeklarowana.Czy istnieje sposób odnoszenia się do stałej C, która nigdy nie została zdefiniowana/zadeklarowana?

Szukam CMD_REQ_REDIS_MGET w The hiredis-vip client library for Redis. Zrobiłem to za pomocą github/google i otrzymałem wyniki dokładnie w dwóch plikach dla pięciu wystąpień. Próbowałem również grep na ciąg w kodzie źródłowym.

$ grep -rnw ./ -e "CMD_REQ_REDIS_MGET" 
./command.c:241: case CMD_REQ_REDIS_MGET: 
./command.c:574:     r->type = CMD_REQ_REDIS_MGET; 
./hircluster.c:3257:  if (command->type == CMD_REQ_REDIS_MGET) { 
./hircluster.c:3446:  if (command->type == CMD_REQ_REDIS_MGET) { 
./hircluster.c:3480: if (command->type == CMD_REQ_REDIS_MGET) { 

Kod źródłowy nie zawiera żadnych plików binarnych i powinien być samodzielny. Nie zawiera żadnych bibliotek z zewnętrznych źródeł, które są powiązane z Redis, więc przez kilka godzin byłem zdezorientowany.

Powód, dla którego muszę wiedzieć, to to, że próbuję dodać kolejną stałą, tak jak ona, i ciągle dostaję błędy, że deklaracja nie została znaleziona, więc zastanawiam się, czy jest jakaś czarna magia, która dzieje się tutaj z C, którego po prostu nie jestem świadomy.

EDYCJA: Chciałem zaznaczyć, że ten kod faktycznie będzie się kompilował w niezmienionym stanie.

+0

czy na pewno wykonujesz grep na odpowiednim poziomie? takie definicje znajdują się zwykle w pliku .h. –

+0

@ Jean-FrançoisFabre Wykonuję go u podstaw repozytorium git –

Odpowiedz

10

Nie można użyć stałej, która nie była wcześniej zadeklarowana. Ale w tym przypadku stała została zadeklarowana, ale nie trywialnie.

Nie znajdziesz nigdzie ciąg (powinien być w plikach nagłówkowych), ponieważ wartości te są zdefiniowane w makro z command.h użyciu tokena wklejanie (## operatora, który tworzy nowe identyfikatory łącząc stare):

#define DEFINE_ACTION(_name) CMD_##_name, 
typedef enum cmd_type { 
    CMD_TYPE_CODEC(DEFINE_ACTION) 
} cmd_type_t; 
#undef DEFINE_ACTION 

, więc nigdy nie znajdziesz CMD_ + Twojego sufiksu. Potem przez jakiś magii (makro nazwa jest prawdopodobnie nowo w pewnym momencie) dodaje określa wszystkie elementy:

#define CMD_TYPE_CODEC(ACTION)                  \ 
    ACTION(UNKNOWN)                    \ 
    ACTION(REQ_REDIS_DEL)     /* redis commands - keys */       \ 
    ACTION(REQ_REDIS_EXISTS)                  \ 
    ACTION(REQ_REDIS_EXPIRE)                  \ 
    ACTION(REQ_REDIS_EXPIREAT)                 \ 
    ACTION(REQ_REDIS_PEXPIRE)                  \ 
    ACTION(REQ_REDIS_PEXPIREAT)                 \ 
    ACTION(REQ_REDIS_PERSIST)                  \ 
    ACTION(REQ_REDIS_PTTL)                  \ 
    ACTION(REQ_REDIS_SORT)                  \ 
    ACTION(REQ_REDIS_TTL)   

Takie makra są bardzo przydatne, aby uniknąć kopiowania/wklejania, ale do cholery, kiedy starasz się znajdź drogę w kodzie za pomocą grep.

+0

Och, człowieku, nie wiedziałem, że coś takiego może być możliwe. Zrobię więcej badań na temat makr C. Naprawdę doceniam, że zająłeś się tym dla mnie! (Przyjmuję, jak tylko mi wolno) –

+2

'## 'jest operatorem * wklejania znaczników *. Pojedynczy znak '# '(nieużywany tutaj) jest operatorem * stringifying * (nie" * stringing * ") (nie sądzę, że standard używa tego terminu). –

+0

@KeithThompson tak, nie jestem zbyt dobry z nazwiskami. Będę edytować. –