c/c++ / printf 实现

一、源码实现

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

void my_printf(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt); /* 用最后一个具有参数的类型的参数去初始化ap */
    for (; *fmt; ++fmt)
    {
        /* 如果不是控制字符 */
        if (*fmt != '%')
        {
            putchar(*fmt); /* 直接输出 */
            continue;
        }
        /* 如果是控制字符,查看下一字符 */
        ++fmt;
        if ('\0' == *fmt) /* 如果是结束符 */
        {
            assert(0); /* 这是一个错误 */
            break;
        }
        switch (*fmt)
        {
        case '%': /* 连续2个'%'输出1个'%' */
            putchar('%');
            break;
        case 'd': /* 按照int输出 */
        {
            /* 下一个参数是int,取出 */
            int i = va_arg(ap, int);
            putchar(i);
        }
        break;
        case 'c': /* 按照字符输出 */
        {
            /** 但是,下一个参数是char吗*/
            /*  可以这样取出吗? */
            char c = va_arg(ap, char);
            putchar(c);
        }
        break;
        case 's':
        {
            char *pc = va_arg(ap, char *);
            while(*pc)
                putchar(*pc++);
        }
        break;
        }
    }
    va_end(ap);
    return;
}

int main()
{
    my_printf("%s %s %c%c%c%c%c!\n", "welcome", "to", 'C', 'h', 'i', 'n', 'a');
    return 0;
}

二、缺陷分析

代码编译时会提示警告:

test_printf.c:41:33: warning: ‘char’ is promoted to ‘int’ when passed through ‘...’
             char c = va_arg(ap, char);

不处理,直接执行程序,发现程序崩溃了。

问题就在于这行代码:

char c = va_arg(ap, char);

这里面会涉及“默认参数提升”的情况。

C语言中什么时候会牵扯到默认参数提升呢?

在C语言中,调用一个不带原型声明的函数时:调用者会对每个参数执行“默认实际参数提升(default argument promotions)。同时,对可变长参数列表超出最后一个有类型声明的形式参数之后的每一个实际参数,也将执行上述提升工作。

提升工作如下:

  • float 类型的实际参数将提升到 double 。

  • char、short 和相应的 signed、unsigned 类型的实际参数提升到 int 。

  • 如果 int 不能存储原值,则提升到 unsigned int 。

所以,调用 my_printf 函数时,传入的参数绝对不会是如下类型:

  • char、signed char、unsigned char

  • short、unsigned short

  • signed shortshort int、signed short int、unsigned short int

  • float

所以正确的方案是将代码

char c = va_arg(ap, char);

 改为

int c = va_arg(ap, int);

即可。

 

参考:

https://blog.csdn.net/astrotycoon/article/details/8284501

https://blog.csdn.net/iynu17/article/details/51588199

 

(SAW:Game Over!)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C/C++实现内存特征码搜索可以通过以下步骤来实现: 1. 定义特征码:根据要搜索的目标数据,定义一个特征码,通常使用十六进制表示。特征码可以是一个或多个字节的组合。 2. 获取内存数据:使用内存读取函数(如`memcpy`),将程序需要搜索的内存数据读取到一个缓冲区中。 3. 搜索特征码:在缓冲区中使用循环和条件语句,逐字节地比较缓冲区的数据和特征码。如果找到完全匹配的特征码,就说明目标数据被找到了。 4. 返回结果:如果找到了特征码,返回找到的位置或索引;如果没有找到,返回一个指定的特殊值(如-1)表示没有找到。 下面是一个简单的示例代码,用于在一个整数数组中搜索特定的整数值的内存特征码: ```cpp #include <stdio.h> #include <string.h> int searchMemory(const int* data, int dataSize, int target) { const int* p = data; for (int i = 0; i < dataSize; i++) { if (*p == target) { return i; } p++; } return -1; } int main() { int data[5] = {1, 2, 3, 4, 5}; int target = 4; int result = searchMemory(data, sizeof(data)/sizeof(data[0]), target); if (result != -1) { printf("Target found at index: %d\n", result); } else { printf("Target not found\n"); } return 0; } ``` 这个示例中,`searchMemory`函数接受一个整数数组、数组大小和目标整数作为输入,然后在数组中搜索目标整数。如果找到,函数返回目标整数在数组中的索引;如果没有找到,返回-1。在`main`函数中,我们定义了一个整数数组和一个目标整数,然后调用`searchMemory`函数进行搜索。最后,根据函数的返回值输出相应结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值