免费注册 查看新帖 |

Chinaunix

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

printf为什么会这样? [复制链接]

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-12-27 12:28 |只看该作者 |正序浏览
看看这个程序的执行结果:
  1. char *Func(int n)
  2. {
  3.     static char s[20];

  4.     sprintf(s, "number %d", n);

  5.     return s;
  6. }

  7. main()
  8. {
  9.     printf("%s, %s\n", Func(1), Func(2));
  10. }
复制代码

为什么是number 1, number 1?

论坛徽章:
0
120 [报告]
发表于 2008-01-25 09:41 |只看该作者
看了这些帖子觉得自己懂的东西都在表面上.....
受教了!
谢谢各位

论坛徽章:
0
119 [报告]
发表于 2005-01-27 12:15 |只看该作者

printf为什么会这样?

win_hate的结论正确。可以参看他给出的几个连接。

论坛徽章:
0
118 [报告]
发表于 2005-01-27 11:27 |只看该作者

printf为什么会这样?

最后的结论对吗?

论坛徽章:
0
117 [报告]
发表于 2005-01-02 10:33 |只看该作者

printf为什么会这样?

关于function参数次序问题:

win_hate的坚强结论,和earo的结论是正确的.
我的说法完全不对.

初始的习惯不是C的标准. 根据机器的情况而定.
好象是这样的:
对于STACK往低地址增长的CPU,从右向左(R2L)
对于STACK向高地址增长的CPU,L2R.

节日愉快

论坛徽章:
0
116 [报告]
发表于 2004-12-31 20:32 |只看该作者

printf为什么会这样?

原帖由 "GCC 3.4.3 Manual" 发表:

8 Binary Compatibility

Binary compatibility encompasses several related concepts:

application binary interface (ABI)
    The set of runtime conventions followed by all of the tools that deal with binary representations of a program, including compilers, assemblers, linkers, and language runtime support. Some ABIs are formal with a written specification, possibly designed by multiple interested parties. Others are simply the way things are actually done by a particular set of tools.
ABI conformance
    A compiler conforms to an ABI if it generates code that follows all of the specifications enumerated by that ABI. A library conforms to an ABI if it is implemented according to that ABI. An application conforms to an ABI if it is built using tools that conform to that ABI and does not contain source code that specifically changes behavior specified by the ABI.
calling conventions
    Calling conventions are a subset of an ABI that specify of how arguments are passed and function results are returned.

.......

Some GCC compilation options cause the compiler to generate code that does not conform to the platform's default ABI. Other options cause different program behavior for implementation-defined features that are not covered by an ABI. These options are provided for consistency with other compilers that do not follow the platform's default ABI or the usual behavior of implementation-defined features for the platform. Be very careful about using such options.

论坛徽章:
0
115 [报告]
发表于 2004-12-31 19:23 |只看该作者

printf为什么会这样?

char *Func(int n)
{
    static char s[20];

    sprintf(s, "number %d", n);

    return s;
}

main()
{
    printf("%s, %s\n", Func(1), Func(2));
}

函数Func返回的是静态数组的首地址,所以每次调用返回的值是一样的。也就是说调用printf时压入栈中的两个参数是一样的,printf在运行时跟据栈中的值计算输出的内容,当然输出两个相同的字符串。

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
114 [报告]
发表于 2004-12-31 16:40 |只看该作者

printf为什么会这样?

http://info.borland.com/techpubs/delphi/delphi5/oplg/procfunc.html
讲解传值约定的,虽然是delphi的。

论坛徽章:
0
113 [报告]
发表于 2004-12-31 16:23 |只看该作者

printf为什么会这样?


  1. 0 1 2
  2. &k = 7f7f07d0  &1 7f7f07ac &2 7f7f07a8 &3 7f7f07a4 &4 7f7f07a0
复制代码

hp unix 11.0
命令:cc test.c

论坛徽章:
0
112 [报告]
发表于 2004-12-31 14:53 |只看该作者

printf为什么会这样?

思兄:

不必客气,你我讨论都是想把问题弄清楚而已。也祝你新年快乐。


我用的就是默认编译选项,即
cc foo.c

如果我用了特殊选项,一定会说明的。

gcc 可以用  attribute 来修饰一个函数,并改变起参数传递行为。但在我印象里,只能选择 __cdecl 和 stdcall。我没有使用任何修饰,此外,attribute 修饰肯定超出了标准 c 的范围,是实现相关的。c 标准中没有任何地方提到了 cdecl 或 stdcall。再此外,一些平台上的 gcc 不支持这种修饰。

关掉寄存器优化的选项我没有见到 (ppc),我估计不会有的。你想,printf 的代码是编译好了的,如果我改动编译选项就使传递方式发生改变,则 printf 必须至少有两个预编译版本。当然,对自己写的函数,有可能改动。但我用的都是默认的方式。


  1. #include <stdio.h>;
  2. func(int i1, int i2, int i3, int i4,...)
  3. {
  4. int k;


  5.   printf("&k = %p  &1 %p &2 %p &3 %p &4 %p\n",  &k, &i1, &i2, &i3, &i4);

  6. }

  7. main()
  8. {
  9. int i = 0;
  10.   printf("%d %d %d\n", i++, i++, i++);
  11.   func(1, 2, 3, 4, 5, 6, 7, 8);
  12. }
复制代码


cc -ggdb 是我能想到的最糟糕的编译方式了。

原帖由 "ppc" 发表:

[zxl@PPC src]$ gcc -v
Reading specs from /usr/lib/gcc-lib/ppc-yellowdog-linux/3.2.2/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=ppc-yellowdog-linux
Thread model: posix
gcc version 3.2.2 20030217 (Yellow Dog Linux 3.0 3.2.2-2a)
[zxl@PPC src]$ gcc -ggdb syk.c
[zxl@PPC src]$ ./a.out
0 1 2
&k = 0x7ffffa60  &1 0x7ffffa50 &2 0x7ffffa54 &3 0x7ffffa58 &4 0x7ffffa5c
[zxl@PPC src]$

原帖由 "x86_64" 发表:

[zxl@AMD64 cu]$ gcc -v
Reading specs from /usr/lib64/gcc/x86_64-mandrake-linux-gnu/3.4.1/specs
Configured with: ../configure --prefix=/usr --libdir=/usr/lib64 --with-slibdir=/lib64 --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --enable-long-long --enable-__cxa_atexit --enable-clocale=gnu --disable-libunwind-exceptions --enable-languages=c,c++,ada,f77,objc,java --host=x86_64-mandrake-linux-gnu --with-system-zlib
Thread model: posix
gcc version 3.4.1 (Mandrakelinux 10.1 3.4.1-4mdk)
[zxl@AMD64 cu]$ gcc -ggdb syc.c
[zxl@AMD64 cu]$ ./a.out
2 1 0
&k = 0x7fbffff32c  &1 0x7fbffff33c &2 0x7fbffff338 &3 0x7fbffff334 &4 0x7fbffff330
[zxl@AMD64 cu]$


行为是不一样的。

>;>; 思兄,你所做的观测都是在 x86 平台上的。在该平台上,参数多数都是从右到左处理的。这点我不否认。

>;>; pascal 在 x86 平台上也一般从左到右处理参数,因为它不需要支持可变参数个数。
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP