作者tinlans ( )
看板PLT
标题Re: [问题] 请问call by address
时间Wed Apr 11 17:50:17 2007
※ 引述《caml (suitengu)》之铭言:
: : 推 jtmh:这里的 object 指的是 variable, 在 K&R C 那本常看到这麽用 04/01 00:48
: : 推 tinlans:一楼正解,PL 教科书和 C 标准规格书也会这样用。 04/01 08:35
: : 推 caml:c的传值会生成temp obj?? c++学太多了吧 04/01 09:40
: : 推 Lordaeron:这就是问题了, object 以现在的眼光来看, 另有意义了. 04/01 09:59
: : 推 tinlans:回三楼,&var 确实会生成一个 temp obj。 04/06 03:37
:
: 你到wiki上查一下evaluation strategy
: 在call by reference条目下﹐
C 只有 call by value,
没有 call by address/reference,
foo(&var) 这种呼叫不管在 C or C++,
只要 foo() 的 parameter type 是 pointer type
(programmer 在 argument 写 &var,而 pass 的是 argument 的 R-value),
这种就叫 call by value。
: If the argument expression is an L-value, its address is used.
所以上面这行只适用於 C++ 才有的 reference type parameter,
当 call site 写 foo(var)
(programmer 在 argument 写 var,而 pass 的是 argument 的 L-value),
且 foo() 的宣告式是 void foo(T &) 时才适用。
: Otherwise, a temporary object is constructed by the caller and
: a reference to this object is passed; the object is then discarded
: when the function returns.
: 推 godfat:这不也是表达 var 是 obj...? 04/11 12:04
: 推 caml:我说的意思是c传值不产生什麽temp obj, 传个地址还生成obj 04/11 12:17
: → caml:效率太低了。 04/11 12:21
这没办法,
虽说 compiler 的 optimization 可以省下一些事情,
然而还是有些事情不能避免,
一般来说如果系统不提供纯正的 absolute addressing mode (且不可重新定址),
取 variable 的 address 通常还是要靠「算」的 (local variable),
甚至是透过二次间接定址从 memory 内的表格「读」出来 (global variable),
不同硬体架构会有不同情形,
但几乎都逃不掉「算」和「读」,
而参数传递时也存在着「写」的动作
除非是硬体设计上有支援「把运算结果直接写入 memory 中某个 address」的功能,
但这种 machine-dependent optimization 已经失去一般性了。
============================================================================
call by value:
int foo(int *ptr) // 此处会将 &var 的值由 stack 上的参数区复制一份
// 到 local variable 区 (可最佳化)。
{
int var2 = 0;
ptr = &var2; // &var2 的新值是写到 local variable 区里放 ptr
// 的地方。
...
}
int main()
{
int var = 0;
return foo(&var); // &var 算式的结果会是一份 temporary object,
// 这个 temporary object 还要 push 到 stack
// 进行参数传递动作 (可由最佳化合并)。
}
============================================================================
call by address/reference:
int foo(int &obj) // 同上例
{
int var2 = 0;
obj = var2; // 此处语法和语意都与上例不同,虽同样是修改「参数」
// 本身,却是得将上例改写成 *ptr = var2; 才会相同,
// 但是「语法依然相异」,而这个「语法」上的不同,也
// 是 value 和 address/reference 传递法上的差异。
...
}
int main()
{
int var = 0;
return foo(var); // 同上例,但注意「programmer 并没有对 var 做运算」
// ,这件事很重要,因为这就是 call by value 和
// call by address/reference 的差异之一。
}
============================================================================
回到前面我说的四行话:
在 C 要送变数的 address/reference 只能用 address-of 运算子取出 lvalue,
但这样会 explicit 构成一个 temporary object (programmer 可见),
所以送过去的会是 temporary object 的 value,
也因此这个还是 call by value。
附上推文:
3F 推 caml:c的传值会生成temp obj?? c++学太多了吧
5F 推 tinlans:回三楼,&var 确实会生成一个 temp obj。
第二行末括的 (programmer 可见),
意思就是说「这样搞结果还是 call by value」的意思,
换言之就是「C 不管怎样还是只有 call by value」的意思,
所以我不清楚你去查「call by refernce」的条目来回的意义。
当然光是这四行是有漏洞的,
所以再往前推三行可以看到我说了:
在 C/C++ 分辨这种东西很单纯是看 call site 怎样写,
不经型别转换就自动取 lvalue 丢进去那就是 by address/reference,
其余的都是 by value,
那四行是这里第一行的详述 (意思相同,在说为什麽看 call site 就能判定),
而这里的第二行和第三行则是补述第一行的不足之处,
「型别转换」是指 implicit type conversion (又叫 coercion)
以及 explicit type conversion (又称 cast),
而我之所以补这两行的原因是在於,
有人会拿 array 跟 function 来做反驳:
在 call site 明明没有看到 & 这个 address-of operator,
那又为什麽还是被叫做 call by value 呢?
答案是这里有 implicit type conversion:
function -> pointer 转换
array -> pointer 转换
这个转换後的 pointer 本身也是 temporary object,
而 callee 收到的是这个 temporary object 的副本,
所以这个也叫做 call by value。
讲到这边来回到你最後说的部分:
推 caml:我说的意思是c传值不产生什麽temp obj, 传个地址还生成obj
→ caml:效率太低了。
综合上面所述,
我所要回答的主旨是:
1. 事实上,C 传值是会产生 temporary object 的 (在 reg 或 stack 上)。
2. 传地址过去其实还是一种传值,所以还是有 temporary object,
实际上这个 temp obj 不管 by value 还是 by addr/ref 都跑不掉,
只是 compiler 可以透过最佳化来减少它,
但是藉由最佳化机制消去的 temporary object,
它本身还是被称之为 temporary object,
不会因为它被 compiler 砍了就失去这个名字。
因此,foo(var) 和 foo(&var) 相较之下,
&var 是一个运算式 (而我们 pass 过去的是 &var 运算式结果的 R-value),
这个「&var 运算式结果」本身就是一个 temporary object,
这会比 foo(var) 还多了一个 temporary object,
因为 foo(var) 这样写并没有对 var 本身做运算。
3. C++ 写太多并不会影响我对 C 的观念,
C++ 我是写了 10 年多,
但是 C 我已经写了快 20 年,
所以应该不是你所想的那样;
另外,我是在 PL 实验室里专门在做 compiler 的。
--
Name: Tseng, Ling-hua E-mail Address:
[email protected]
School: National Tsing Hua University Department: Computer Science
Interesting: C++, Compiler, PL/PD, OS, VM, Large-scale software design
Researching: Software pipelining for VLIW architectures
Homepage:
https://it.muds.net/~uranus
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 61.230.216.206
※ 编辑: tinlans 来自: 61.230.216.206 (04/11 18:10)
1F:推 aoc90058:推一个 :) 04/11 22:24
2F:推 yago01:真不愧是LPC之神... 04/12 11:38
3F:推 revivalworld:推鹿神 04/22 17:28