gcc 在C语言中使用printf()重新实现printf()

3mpgtkmj  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(224)

我正在做一个嵌入式linux项目,我想做一个简单的调试消息库,当我的代码处于生产阶段时,我可以在那里禁用我的调试消息(使用预编译指令),并在将来替换数据库中的某种类型的日志。由于va_list,我在重新实现printf()时遇到了麻烦。这是我到目前为止的代码:
我的源文件:

#include "debug_msgs.h"

#define ENABLE_DEBUG_MSGS   1U

#if ENABLE_DEBUG_MSGS

int print(const char *fmt, ...) {
    int n = -1;
    va_list ap;
    va_start(ap, fmt);
    n = printf(fmt, ap);
    va_end(ap);
    return n;
}

#else

int print(const char *fmt, ...) {
    return 0;
}

#endif

我的头文件:

#ifndef DEBUG_MSGS_H
#define DEBUG_MSGS_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include <unistd.h>

int print(const char *fmt, ...);

#endif

我的问题是:我的实现可以编译(我知道这并不意味着什么),但是当我做一个简单的测试时,比如:

int num1 = 10;
int num2 = 100;
int num3 = 1000;
float floating = 3.14;
char str[] = {"Please work, please"};
int number=-1;
number = print("\nTesting %d %d %d %f %s\n", num1, num2, num3, floating, str);
printf("\nnumber = %d\n",number); //Just to check the return

我会得到以下输出:

Testing -1095005212 100 -1095005212 -0.000002 H*� 

number = 52

补充信息:
这是我的平台信息:Linux mdm9607 3.18.44 #1 PREEMPT Tue Sep 13 19:45:33 UTC 2022 armv7l GNU/Linux
我的编译器信息:arm-oe-linux-gnueabi-gcc
我的$CFLAGS:-O2 -fexpensive-optimizations -frename-registers -fomit-frame-pointer -MMD -MP
我的$LDFLAGS:
-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed

LDFLAGS += -lumdp -lumdpcommon
LDFLAGS += -lpthread -lxml2 -lrt
LDFLAGS += -lm
e5nszbig

e5nszbig1#

您应该使用vprintf或带有va_list参数的vfprintf,而不是printf

#include <stdarg.h>
#include <stdio.h>

int print(const char *fmt, ...) {
    int n;
    va_list ap;
    va_start(ap, fmt);
    n = vprintf(fmt, ap);
    va_end(ap);
    return n;
}

编译错误代码的原因是printf作为vararg函数,可以接受格式字符串之后的任何参数类型。但是,您可以通过启用更多编译器警告来避免printf参数的类型不匹配:gcc -Wall -Wextra -Werror至少会抱怨将printf与非常量格式字符串一起使用,并且如果格式字符串是字符串文字,则会执行编译时类型检查。

相关问题