我正在C / Linux中实现printf功能

时间:2017-09-27 23:13:33

标签: c linux printf

程序:

 #ifndef PRINTF_H
 #define PRINTF_H
 #include "my_put_char.h"

 int my_printf(char *str, ...);

 #endif

这是我的函数的Header文件。

#include <stdio.h>
#include "my_put_char.h"

void my_put_char(char c) 
{
     fwrite(&c, sizeof(char), 1, stdout);
}

这是我的putchar实现(my_put_char.c)。

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "printf.h"

int my_printf(char *str, ...)
{   
    if(str == NULL)
        return 0;

    int i;
    char a;

    va_list print;
    va_start(print,str);

    for(i = 0; str[i] ; i++)
    {
        if(str[i] == '%')
        {
            i++;
            switch(str[i])
            {
                case 'c':
                a = va_arg(print, char);
                my_put_char(a);
                break;
            }
        }
     }
     va_end(print);
     return 0;
}

最后,这是我的printf实现的一部分。 我正在使用%c进行测试以显示一个字符。

当我my_print("%c", 'd'); main.c时 它编译并显示d

但是当我my_print("%c", "hi");时,它仍会编译并显示一个数字。

问题:

a = va_arg(print, char);之后(或之前)有没有办法检查我的输入是否是不同的数据类型? 如果我的输入是不同的数据类型,我正在尝试显示错误。

我在这个问题上已经有2天了,找不到任何答案。 非常感谢你的时间!

1 个答案:

答案 0 :(得分:3)

  

当我my_print("%c", "hi");时,它仍会编译并显示一个数字

您已获得一些undefined behavior,因此请scared。您的my_printf会使用错误类型的参数调用va_arg(预期char提升为int,获得char*

为了解释发生了什么,你应该深入了解实现细节(查看汇编代码,例如gcc -Wall -fverbose-asm -O -S;研究你的processorinstruction set architectureapplication binary interfacecalling conventions)。 您不想这样做,可能需要数年时间才能重现。

立即阅读Lattner's blog on UB

然后下载C11规范n1570 ....

您还可以使用gcc使用function attributes。不要忘记编译所有警告和调试信息(gcc -Wall -Wextra -g

  编写a = va_arg(print, char);之后

有没有办法检查我的输入是否是不同的数据类型?

不,不是真的,也不是永远。但format函数属性可能会有所帮助。您还可以花费数月时间使用自己的plugin或一些GCC MELT扩展程序自定义GCC(这不值得您花时间)。请注意Halting ProblemRice's Theorem(每个static源代码program analysis都具有挑战性)。另请参阅Frama-C等源分析工具。

  

我正在实施printf功能

BTW研究free software的现有C standard library实施的源代码(例如GNU glibcmusl-libc)可能是鼓舞人心的;它们基于syscalls(2)