免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: dn2010
打印 上一主题 下一主题

[函数] 元芳,这道题做面试题怎么样? [复制链接]

论坛徽章:
0
11 [报告]
发表于 2012-11-29 21:53 |只看该作者
socay2 发表于 2012-11-29 12:45
不要传递类似于 "06" 这样的字符串常量。你在 strcpy 的时候肯定报错,因为常量不能修改。


那你没用过 IBM 的 AS/400 机器吧?

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
12 [报告]
发表于 2012-11-29 21:53 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
13 [报告]
发表于 2012-11-29 21:58 |只看该作者
pmerofc 发表于 2012-11-29 21:53
回复 10# dn2010
undefined behavior


谢谢!
在AS/400上,用15编译(相当于生成.o/.obj),再用 CRTPGM 生成 *PGM (相当于 LINK 成 .exe) 。CRTPGM 的选项 ACTGRP 选 *CALLER 还是 *NEW,
对该程序的运行结果影响巨大。

论坛徽章:
0
14 [报告]
发表于 2012-11-29 22:14 |只看该作者
socay2 发表于 2012-11-29 12:45
不要传递类似于 "06" 这样的字符串常量。你在 strcpy 的时候肯定报错,因为常量不能修改。


正因为在 OS/400 平台它不报错,所以我们得要求文档中说明为 INPUT 的参数,就不得修改,只能修改说明为 OUTPUT 的参数。
某些公司的产品就存在这样的问题。

论坛徽章:
0
15 [报告]
发表于 2012-11-29 22:19 |只看该作者
回复 7# dn2010


    嗯,gcc

论坛徽章:
0
16 [报告]
发表于 2012-11-29 22:32 |只看该作者
把程序再改进一下:
  1. /* 运行结果依赖平台和该平台编译器设置的程序

  2.    OS/400: CRTPGM的ACTGRP: *CALLER和*NEW时多次CALL 本程序的结果不同。
  3.    Windows: 修改字符串常量将报错退出(0xC0000005: Access Violation)
  4.    Linux:   修改字符串常量将coredump
  5. */

  6. #include <stdio.h>
  7. #include <string.h>

  8. int func3(char *p1, char *p2, char *fmt)
  9. {
  10.   printf("@func3(), fmt addr:%p\n", fmt);
  11.   printf("@func3(), p1=%s, p2=%s, fmt=%s\n", p1, p2, fmt);
  12.   return 0;
  13. }

  14. int func2(char *p1, char *fmt)
  15. {
  16.   printf("@func2(), fmt addr:%p\n", fmt);
  17.   printf("@func2(), p1=%s, fmt=%s\n", p1, fmt);
  18.   if(strcmp(fmt, "06") == 0)
  19.   {
  20.     strcpy(fmt, "01");
  21.     printf("@func2(), fmt: 06->01\n");
  22.   }
  23.   else
  24.   {
  25.     printf("@func2(), fmt: %s->06\n", fmt);
  26.     strcpy(fmt, "06");
  27.   }
  28.   return 0;
  29. }

  30. int func1(char *s1)
  31. {
  32.   func2(s1, "06"); /* 这里的"06"和下一行的"06"是否会优化成指向同一个地址? */
  33.   func3(s1, "1313", "06");
  34.   return 0;
  35. }

  36. void *upperAstr(void *str)
  37. /*
  38.    ASCII字符串中的小写字母变大写
  39. */
  40. {
  41.   int  i, n;
  42.   char *p = (char *)str;

  43.   n = strlen(p);
  44.   for(i = 0; i < n; i++)
  45.   {
  46.     if(p[i] >= 0x61 && p[i] <= 0x7A)      /* 'a'-'z' */
  47.       p[i] -= 0x20;
  48.     if(p[i] == 0x00) break;
  49.   }
  50.   return str;
  51. }

  52. void *upperStr(void *str)
  53. /*
  54.    当前环境(ASCII or EBCDIC) 字符串中的小写字母变大写
  55. */
  56. {
  57.   int  i, j, n;
  58.   char *p = (char *)str;
  59.   char *u = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  60.   char *l = "abcdefghijklmnopqrstuvwxyz";

  61.   n = strlen(p);
  62.   for(i = 0; i < n; i++)
  63.   {
  64.     for(j = 0; j < strlen(l); j++)
  65.     {
  66.       if(p[i] == l[j])
  67.       {
  68.         p[i] = u[j];
  69.         break;
  70.       }
  71.     }
  72.     if(p[i] == 0x00) break;
  73.   }
  74.   return str;
  75. }

  76. #define      HELLO "  Hello   World! "
  77. main(int argc, char **argv)
  78. {
  79.   unsigned char *s1 = HELLO;
  80.   char *s2          = HELLO;

  81.   printf("----------Begin run <%s>\n", argv[0]);
  82.   printf("s1=<%s>\n", s1);
  83.   printf("s2=<%s>\n", s2);
  84.   printf("s1 addr=%p\n", s1);
  85.   printf("s2 addr=%p\n", s2);
  86.   upperStr(s1);
  87.   printf("----s1变大写之后:\n");
  88.   printf("s1=<%s>\n", s1);
  89.   printf("s2=<%s>\n", s2);
  90.   printf("s1 addr=%p\n", s1);
  91.   printf("s2 addr=%p\n", s2);

  92.   func1("111");
  93.   func1("222222");
  94.   func1("333");

  95. #ifdef __OS400__
  96.   printf("按'执行'键退出本程序.\n");
  97.   getchar(); /* 以免CALL本程序后“一闪而过”看不清前面printf的结果 */
  98. #endif
  99. }
复制代码
如果本程序拿来做面试题,考的有这几点:
1、字符串常量是否允许修改与平台有关
2、重复的字符串常量的优化问题
3、OS/400平台的ACTGRP概念和影响

论坛徽章:
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
17 [报告]
发表于 2012-11-30 09:13 |只看该作者
dn2010 发表于 2012-11-29 21:51
你不知道该程序在 OS/400 上是能跑的。

确实不知道
但即使它在一切平台上都能跑,它也是错误的呀
因为就是这么规定呀,C语言没有规定它一定会正确

论坛徽章:
1
巨蟹座
日期:2014-03-18 23:44:30
18 [报告]
发表于 2012-11-30 09:33 |只看该作者
dn2010 发表于 2012-11-29 22:14
正因为在 OS/400 平台它不报错,所以我们得要求文档中说明为 INPUT 的参数,就不得修改,只能修改说明为 ...


在C中所谓的 INPUT/OUTPUT  也只是一个空宏,形式而已。你如果要修改,还是可以照常修改。

论坛徽章:
1
巨蟹座
日期:2014-03-18 23:44:30
19 [报告]
发表于 2012-11-30 09:34 |只看该作者
回复 11# dn2010


    嗯,不好意思,没用过 IBM 的机子。

论坛徽章:
0
20 [报告]
发表于 2012-11-30 20:35 |只看该作者
bruceteen 发表于 2012-11-30 09:13
确实不知道
但即使它在一切平台上都能跑,它也是错误的呀
因为就是这么规定呀,C语言没有规定它一定会正 ...


不过现在你知道了。

另外我再说一个东西,可能不少人都不知道:
C 程序的 main 函数:int  main(int argc,  char **argv)
在大部分平台上,这里的argv是拿来“接收”命令行参数的,例如在 Unix 的shell 程序中调用你的一个C语言程序 mycprog:
mycprog  参数1  参数2  参数3 ...
对于C程序来说,上述命令行参数全部是INPUT类型的参数,就是说在很多平台上你不允许改,或者你改了调用者也拿不到,而C程序执行完成返回调用者的只能是一个整数。如果调用者想要一个字符串,那就得另想办法,例如写到文件里。
当你在AS/400的平台上干活,IBM 允许C程序的main函数的这些 argv 参数(除了argv[0])都可以是OUTPUT的,这样CLP程序(类似于UNIX的SHELL程序)就可以拿到C程序返回的字符串,而不用通过文件等低效率的途径,这在很多场合都是很有用的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP