免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2439 | 回复: 3
打印 上一主题 下一主题

[C] 动态参数传递中的指针传递 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-03-06 15:32 |只看该作者 |倒序浏览
本帖最后由 慕冬亮 于 2014-03-06 15:32 编辑

我在看《一个操作系统的实现》这本书的时候,看到io这一章的最后一个例子,我想把书中的printk(书中是printf) 补充一下,但是在实现%s的时候出现了问题,打印出来的字符串和我所说的字符串不同,调试的时候发现地址都不一样。下面让我们先看看函数!
int printk(const char *fmt,...)
{
        int i;
        char buf[256];
        va_list arg = (va_list)((char *)(&fmt) + 4);
        i = vsprintk(buf,fmt,arg);
        write(buf,i);
        return i;
}
int vsprintk(char *buf,char *fmt,va_list args)
{
        char *p;
        char tmp[256];
        va_list p_next_arg = args;
        for(p=buf;*fmt;fmt++)
        {
                if(*fmt != '%')
                {
                        *p++ = *fmt;
                        continue;
                }
                fmt++;
                switch(*fmt)
                {
                        case 'x':
                                itoa(tmp,*((int *)p_next_arg));
                                strcpy(p,tmp);
                                p_next_arg += 4;
                                p +=strlen(tmp);
                                break;
                        case 's':
                                strcpy(p,(char *)p_next_arg);
                                p_next_arg += 4;
                                p += strlen((char *)p_next_arg);
                                break;
                }
        }
        return (p-buf);
}
在主调函数中,调用的代码如下:
char test[]="abcd";
printk("%s",test);
结果发现打印的不是abcd,乱七八糟的字符。我在调试的时候将test的值和p_next_arg的值比对,两者竟然不相等,不知道为什么????
补充:va_list  是 typedef char* va_list;

论坛徽章:
0
2 [报告]
发表于 2014-03-06 16:35 |只看该作者
回复 1# 慕冬亮
  1.         char** argv = (char**)(&fmt);
  2.         va_list arg=argv[1];
复制代码

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
3 [报告]
发表于 2014-03-06 16:40 |只看该作者
为什么不用 va_arg 等可移植的代码?
  1. #include <stdio.h>
  2. #include <stdarg.h>

  3. int vprintk( const char *fmt, va_list args )
  4. {
  5.     int ret = 0;

  6.     for( const char* p=fmt; *p; ++p )
  7.     {
  8.         if( *p != '%' )
  9.         {
  10.             putchar( *p );
  11.             ++ret;
  12.             continue;
  13.         }

  14.         if( *++p == '\0' )
  15.             break;

  16.         switch( *p )
  17.         {
  18.         case 'x':
  19.             ret += printf( "%x", va_arg(args,unsigned int) );
  20.             break;
  21.         case 's':
  22.             ret += printf( "%s", va_arg(args,const char*) );
  23.             break;
  24.         }
  25.     }

  26.     return ret;
  27. }

  28. int printk( const char *fmt, ... )
  29. {
  30.     va_list args;
  31.     va_start(args, fmt);
  32.     int n = vprintk( fmt, args );
  33.     va_end( fmt );

  34.     return n;
  35. }

  36. int main()
  37. {
  38.     int n = printk( "ABC - %s, DEF - %x\n", "abc", 123 );
  39.     printf( "%d\n", n );

  40.     return 0;
  41. }
复制代码

论坛徽章:
0
4 [报告]
发表于 2014-03-07 13:24 |只看该作者
我知道Linux内核中在使用这个几个宏,va_start,va_end,var_arg。然而我看这本书,是在自己写底层操作系统,是不可以借助库函数和Linux源码,不过现在问题已经解决啦,另外我想着可以可以把Linux内核的宏移植到这个系统中,这几个宏确实很好用!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP