系统程序设计学习笔记

今天主要看了作用域和传值传引用以及递归,都是十分典型的问题,而且我发现卡耐基上面讲的很不错,所以做一下笔记。

首先是作用域,这里有一个典型的程序:

#include <stdio.h>

int first;
int second;

void callee ( int first )
{
        int second;

        second = 1;
        first = 2;
        printf("callee: first = %d second = %d\n", first, second);
}

int main (int argc, char *argv[])
{
        first = 1;
        second = 2;
        callee(first);
        printf("caller: first = %d second = %d\n", first, second);
        return 0;
}


从这里面我明白局部作用域的优先级高于全局作用域。还有就是程序在调用函数之前会对参数做一个复制(如果是传值的话),那么这个局部对象怎么才能观察到呢?还没解决。

另外就是传值和传引用。

#include <stdio.h>

int first;
int second;

void callee ( int * first )
{
        int second;

        second = 1;
        *first = 2;
        printf("callee: first = %d second = %d\n", *first, second);
}

int main (int argc, char *argv[])
{
        first = 1;
        second = 2;
        callee(&first);
        printf("caller: first = %d second = %d\n", first, second);
        return 0;
}
这个程序只是传指针,其实还是传值,因为指针的值是通过传值传进去的。其实传引用只是改变了一下形势,传指针和传引用是等价的。

标准的传值

void fun(int a);

标准的传引用

void fun(int& a);


#include <stdio.h>
#include <stdlib.h>

void callee (int n)
{
        if (n == 0) return;
        printf("%d (0x%08x)\n", n, &n);
        callee (n - 1);
        printf("%d (0x%08x)\n", n, &n);
}

int main (int argc, char * argv[])
{
        int n;

        if (argc < 2) 
        {
                printf("USAGE: %s <integer>\n", argv[0]);
                return 1;
        }
        
        n = atoi(argv[1]);
        
        callee(n);
        return 0;
}
下面这段话讲的很好:

What happens is that the compiler inserts additional code for every function call and every function return. This code allocates any local variables that the callee needs for that invocation. Multiple invocations of the callee activate this allocation code over and over again. This is called dynamic allocation, because the local variables are allocated at runtime, as needed.

Global variables can be allocated statically. This means that the compiler can fix specific addresses for global variables before the program executes. But because functions can be called recursively, and each recursive invocation needs its own instantiation of local variables, compilers must allocate local variables dynamically. Such dynamic behavior makes the program run more slowly, so it is not desirable. But it is necessary for local variables.

意思就是每次函数调用之前编译器会做一些事情,做什么事情呢?就是插入一些额外的代码。这些代码会为函数分配局部变量。由于程序不知道有多少局部变量,所以全局变量的地址和局部变量的地址相差的很大。



你可能感兴趣的:(系统程序设计学习笔记)