Bootstrap

【整理自用】C++函数传递

这个本来是没什么需要说明的,但是偏偏是错了几道题,发现自己思考不够严谨。

1. 搞清楚到底在说那个变量

函数传递,确实存在着值传递、址传递和引用传递三种。但是要搞清楚着通常是对于什么变量而言的。
以下三个是所谓的值传递,值传递和引用传递最简单的表达形式:

int abs(int a);
int abs(int *a);
int abs(int &a);

对于形如上述的表达式而言,无论是哪一种形式,a本身都是一个局部变量。都是在调用的时候为其创造了一个临时变量,当函数体结束之时,自动销毁的。
也就是说,哪些仅针对a所做的改变,不论是哪一种传递方式,都终将会因为a的销毁而灰飞烟灭。对于调用的函数而言不会产生任何的影响。
下面开始仔细说明:

  1. 值传递:调用函数只是把变量的值传递过来。所以a仅仅只是一个和调用函数实参拥有相同大小的临时变量。
  2. 址传递:调用函数将变量地址传过来。所以a 一个和调用函数实参拥有相同地址的临时变量。
  3. 引用传递:引用比较特殊。因为是实参的别名,所以可以简单认为是调用实参来临时旅游

可能听上去没什么用处,但是其实很重要。比如我们说址传递中,当形参改变时,会影响到实参。前提在于:因为临时变量与原实参共享地址。因此,我通过临时变量更改该地址内的数字,即使事后临时变量消失了,但是原实参地址不变的,所以在同样的地址内看到的东西,自然是已经生效了。

但是,a毕竟只是一个临时变量,如果我不通过临时的东西去和生存周期更长的东西挂钩,那么我短暂做过的事情是不会被人看到的。

题目:下面程序输出的代码是多少?

void f(char * x)
{
    x++;
    *x='a';
}
int main()
{
    char str [sizeof("hello")];
    strcpy(str, "hello");
    f(str);
    cout<<str;
    return 0;
}

分析:
1. str可以看做是字符串数组的首元素指针。字符串数组分配的空间在地址上是连续的;
2. 生成了一个临时性的指针变量x,但是它和str指向同一个地址;
3. x++;使得x(内容)地址自增,从而使得它指向字符串数组第二个元素;
4. *x词句修改了当前x指向地址内部的元素,即字符串数组第二个元素被改变。
5. 此时x变量离开了函数作用域,局部变量被销毁。

综上可见,临时变量x的一生只有一件事是和更长的生长周期挂钩的,那就是修改了实参字符串数组第二个元素。其他只作用在x自身身上的一切行为都随着x自身的消亡而湮灭了,在剩下的函数里我们是见不到半点痕迹的。
因而,上述输出str字符串的结果应该是“Hallo”。


题目: 下面程序的输出结果是:

#include <stdio.h>
#include <stdlib.h>
void fun ( double *pl,double *p2,double *s)
{
    s = ( double*) calloc ( 1,sizeof(double));
    *s = *pl + *(p2+1);
}
main( )
{
    double a [2] = {1.1,2.2},b [2] = {10.0,20.0}, *s = a;
    fun (a,b,s);
    printf ( "%5.2f\n",* s) ;
}

分析:
1. fun(a,b,c)传入参数,a,b,c分别为a,b,a数组的首元素的指针。
2. 创建临时变量p1,p2,s。分别于a,b,a指针拥有同样的地址。
3. s赋值为一个指向含有8个字节内容的某一个地址。
4. s地址内放入了p1指向的地址内存放的元素+(p2+1)指向地址存放的内容。注意“指针+1”是加上一个单位量而不是物理地址的1,但是如果是真实的地址量+1,那就是物理地址+1。
5. 此时临时变量离开了函数作用域,所有局部变量被销毁。

综上可见,临时变量的一生都与更长的生命周期无关,因此对实参不会产生任何影响。
因而答案是:“1.10”

数组名作为形参,退化为指针

在C语言中,数组名作为参数传给函数时,退化为指针;需要数组大小时,需要一个参数传数组名,另一个传数组大小。
即下面的1,2,3行代码是等同的。

int fun(char a[]);
int fun(char a[100]);
int fun(char *a);

题目:某32位系统下, C++程序如下所示,sizeof 的值应为?(22,4 ,4,4)

char str[] = “http://www.renren.com”  (长度为21)
char *p = str ; 

sizeof (str ) = ?
sizeof ( p ) = ?
void Foo ( char str[100]){
    sizeof( str ) = ?
}
void *p = malloc( 100 );
sizeof ( p ) = ?

所以当利用sizeof的时候返回的将是int指针的内存字节数,只能做这样的函数了,void fun(int *a,size_t n);才能知道数组大小。

;