Pergunta Cabeluda sobre string.h [RESOLVIDO]

1. Pergunta Cabeluda sobre string.h [RESOLVIDO]

Nick Us
Nick-us

(usa Slackware)

Enviado em 08/03/2019 - 16:32h

Continuando minha busca para aprender C, resolvi estudar e entender as bibliotecas e como elas funcionam.
Dessa forma, resolvi usar minhas bibliotecas e não as existentes, ao menos por enquanto, para eu conhecer o que existe e o que não existe na linguagem C.
Resolvi então começar por uma bem fácil string.h e pelo comando strlen.

IMPORTANTE: Minha dúvida não é como fazer um strlen, pois EU SEI fazer isso!
Minha dúvida é entender o que está escrito na biblioteca string.h para eu entender como ELES fizeram o strlen deles!

Tentando localizar em meu PC, a biblioteca MAIS ORIGINAL Possível, encontrei essa no Slackware /usr/include/string.h
Se eu estiver estudando a errada, por favor me informem!

Encontrei dentro dela sobre strlen as 2 linhas completas abaixo:
#if defined __USE_GNU && defined __GNUC__
/* Duplicate S, returning an identical alloca'd string. */
# define strdupa(s) \
(__extension__ \
({ \
const char *__old = (s); \
size_t __len = strlen (__old) + 1; \
char *__new = (char *) __builtin_alloca (__len); \
(char *) memcpy (__new, __old, __len); \
}))

///////////////////////////////////////////////////////////////////////

/* Return the length of S. */
extern size_t strlen (const char *__s)
__THROW __attribute_pure__ __nonnull ((1));

Primeiro Problema que não entendi. Lembrando que sou iniciante, então desculpem-me por perguntas tolas...
Os caracteres \ Em shell sei que eles seriam apenas quebras de linha. É o mesmo que acontece acima?

Segundo Problema: Entendi que dentro do #define são tudo comandos normais, o mesmo que fazemos em nosso conhecido main certo?

Obrigado a quem souber ajudar!



  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 08/03/2019 - 20:20h

Nick-us escreveu:

#if defined __USE_GNU && defined __GNUC__
/* Duplicate S, returning an identical alloca'd string. */
# define strdupa(s) \
(__extension__ \
({ \
const char *__old = (s); \
size_t __len = strlen (__old) + 1; \
char *__new = (char *) __builtin_alloca (__len); \
(char *) memcpy (__new, __old, __len); \
}))

///////////////////////////////////////////////////////////////////////

/* Return the length of S. */
extern size_t strlen (const char *__s)
__THROW __attribute_pure__ __nonnull ((1));

Primeiro Problema que não entendi. Lembrando que sou iniciante, então desculpem-me por perguntas tolas...
Os caracteres \ Em shell sei que eles seriam apenas quebras de linha. É o mesmo que acontece acima?


Sim, é como no shell: imediatamente antes da quebra de linha, a barra invertida indica ao preprocessador, que é orientado a linhas (ao contrário do compilador, que tem regras sintáticas que são neutras com relação a espaçamentos e qeubras de linha) que o conteúdo da diretiva #define não termina no final da linha, mas continua na linha seguinte.

Segundo Problema: Entendi que dentro do #define são tudo comandos normais, o mesmo que fazemos em nosso conhecido main certo?


São comandos “normais”, mas repare que ele usa extensões específicas do GCC na definição da macro com cara de função strdupa(), coisas que não existem no C padrão. Por isso, ele testa para garantir que se está usando o GCC e uma versão de biblioteca condizente com o conteúdo usado em sua definição, e é por isso que, antes do #define, ele usa um #if que testa duas macros identificadoras do tipo de compilador (__GNUC__) e da biblioteca (__USE_GNU), e apenas vai permitir que ela seja compilada se ambas estiver definidas. (Faltou, porém, o #endif correspondente ao #if, de modo que eu não sei onde termina essa compilação condicional.)


Você possivelmente já percebeu, mas não custa lembrar que os arquivos .h não implementam nada da biblioteca, mas apenas declaram as funções e definem alguns tipos, macros e constantes. Para conhecer essas declarações e definições de tipos, macros e constantes, você não necessariamente precisaria de ler o arquivo de cabeçalhos, mas a documentação possivelmente seria mais eficiente. Assim, se você quiser realmente estudar como as coisas são por dentro, tem de pegar o código-fonte da biblioteca e ler os .c (e eventualmente alguns .s/.asm), além dos .h.


... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)





Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts