Escrevendo funções semelhantes a printf
Argumentos variáveis.
Escrevendo funções semelhantes a printf é uma aula grátis de C Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C Academy inclui 4 aulas no total.
Funções que recebem uma cadeia de formato
O uso mais poderoso de argumentos variádicos é criar funções no estilo de printf que interpretam uma cadeia de formato.
O formato informa à função quantos argumentos vêm depois e qual é o tipo de cada um.
#include <stdio.h>
#include <stdarg.h>
void myprint(const char *fmt, ...) {
printf("format was: %s\n", fmt);
}
int main(void) {
myprint("%d items\n", 5);
return 0;
}Percorrendo a cadeia de formato
Examine o formato caractere por caractere. Quando encontrar um %, o caractere seguinte será um especificador de conversão que informa qual tipo deve ser lido.
Todo o restante é impresso literalmente.
#include <stdio.h>
#include <stdarg.h>
void scan(const char *fmt) {
for (const char *p = fmt; *p; p++) {
if (*p == '%') printf("[spec:%c]", *(p+1));
else putchar(*p);
}
putchar('\n');
}
int main(void) {
scan("x=%d y=%s");
return 0;
}Lendo o tipo correspondente
Quando o especificador for %d, leia um int. Para %s, leia um char *. O formato deve corresponder exatamente aos argumentos reais.
#include <stdio.h>
#include <stdarg.h>
void mini(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (const char *p = fmt; *p; p++) {
if (*p == '%' && *(p+1) == 'd') {
printf("%d", va_arg(args, int));
p++;
} else putchar(*p);
}
va_end(args);
}
int main(void) {
mini("count=%d\n", 42);
return 0;
}Lidando com vários especificadores
Amplie o analisador para lidar com várias conversões. Adicione casos para %d, %s e %c, lendo o tipo correto em cada caso.
#include <stdio.h>
#include <stdarg.h>
void fmt_print(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (const char *p = fmt; *p; p++) {
if (*p != '%') { putchar(*p); continue; }
p++;
if (*p == 'd') printf("%d", va_arg(args, int));
else if (*p == 's') printf("%s", va_arg(args, char *));
else if (*p == 'c') putchar(va_arg(args, int));
}
va_end(args);
}
int main(void) {
fmt_print("%s is %d\n", "age", 30);
return 0;
}Escapando o sinal de porcentagem
Funções de formato reais tratam %% como um sinal de porcentagem literal. Adicione um caso para que os usuários possam imprimir um % real.
#include <stdio.h>
#include <stdarg.h>
void fp(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (const char *p = fmt; *p; p++) {
if (*p == '%') {
p++;
if (*p == '%') putchar('%');
else if (*p == 'd') printf("%d", va_arg(args, int));
} else putchar(*p);
}
va_end(args);
}
int main(void) {
fp("%d%% done\n", 75);
return 0;
}Encaminhando para vprintf
Muitas vezes, você não quer reimplementar a formatação. A biblioteca padrão oferece vprintf, que recebe uma va_list diretamente.
Sua função de encapsulamento apenas repassa os argumentos.
#include <stdio.h>
#include <stdarg.h>
void logline(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
int main(void) {
logline("value = %d, name = %s\n", 7, "box");
return 0;
}Adicionando um prefixo
A abordagem com vprintf facilita adicionar comportamentos ao redor da formatação padrão, como imprimir uma etiqueta antes de cada mensagem.
#include <stdio.h>
#include <stdarg.h>
void info(const char *fmt, ...) {
printf("[INFO] ");
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
int main(void) {
info("server started on port %d\n", 8080);
return 0;
}Escrevendo em um buffer com vsnprintf
Para formatar em uma cadeia de caracteres em vez de imprimir, use vsnprintf(buf, size, fmt, args).
Ela é limitada por size, evitando estouros, e sempre adiciona um terminador nulo.
#include <stdio.h>
#include <stdarg.h>
void format_into(char *buf, size_t n, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vsnprintf(buf, n, fmt, args);
va_end(args);
}
int main(void) {
char out[64];
format_into(out, sizeof(out), "id-%d", 123);
printf("%s\n", out);
return 0;
}Retornando um comprimento
vsnprintf retorna o número de caracteres que teria sido escrito. Você pode usar esse valor para detectar truncamento ou dimensionar um buffer.
#include <stdio.h>
#include <stdarg.h>
int build(char *buf, size_t n, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int len = vsnprintf(buf, n, fmt, args);
va_end(args);
return len;
}
int main(void) {
char b[10];
int needed = build(b, sizeof(b), "%d-%d", 11, 22);
printf("%s (needed %d)\n", b, needed);
return 0;
}Escolhendo sua abordagem
Há duas estratégias: analisar o formato por conta própria para ter controle total ou encaminhá-lo para vprintf/vsnprintf em busca de correção e de menos código.
Na maior parte do código real, encaminhar é a opção mais segura e simples.
#include <stdio.h>
#include <stdarg.h>
void say(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
}
int main(void) {
say("%s = %.1f\n", "pi", 3.14);
return 0;
}Incompatibilidade causa comportamento indefinido
Se a cadeia de formato promete um tipo que não corresponde ao argumento real, o comportamento é indefinido.
printf("%d", "text") pode causar uma falha. Mantenha sempre o formato e os argumentos sincronizados.
#include <stdio.h>
int main(void) {
int n = 5;
printf("%d\n", n);
return 0;
}Verificação rápida
Teste sua compreensão de funções de encapsulamento no estilo de printf.
Recapitulação
Você aprendeu a criar funções semelhantes a printf:
- Receba uma cadeia de formato como parâmetro nomeado e, depois,
.... - Analise você mesmo os especificadores
%e leia os tipos correspondentes ou - encaminhe a
va_listpara vprintf / vsnprintf para obter uma formatação segura e correta. - Mantenha o formato e os tipos dos argumentos sincronizados para evitar comportamento indefinido.
Perguntas Frequentes
A aula “Escrevendo funções semelhantes a printf” é grátis?
Sim — o texto completo de “Escrevendo funções semelhantes a printf” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C Academy, atualize para CoddyKit PRO. O curso de C Academy inclui 4 aulas no total.
O que vou aprender em “Escrevendo funções semelhantes a printf”?
Argumentos variáveis. Você pratica C Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar C Academy?
Nenhuma experiência prévia é necessária. C Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Escrevendo funções semelhantes a printf”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de C Academy?
Sim. Cada aula de C Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- As macros stdarg
- Escrevendo funções semelhantes a printf
- Questões de segurança de tipos
- Exemplos práticos