C語言學習4: 函數返回值與傳入參數,關於函數值傳遞和類型隱性轉換,變量不一樣的做用域,static變量,多文件編譯例如兩個C文件,顯示函數調用語句跳轉,遞歸,斐波那契數列,多文件編譯相同變量的問題。

1,函數返回值與傳入參數函數

#include <stdio.h>

void foo(void);

// 若是不聲明返回值類型, 那麼返回值類型默認爲int
bar(void);

// 聲明沒有帶參數, 那麼調用時能夠傳遞任意參數.
void test();
//void test1(void);

int main(void)
{
    foo();
    printf("world.\n");
    bar();

    test(3.14, "hello", 123);
    //test1(1, 3.14, "hello");

    return 0;
}

void foo(void)
{
    printf("hello ");
}

bar(void)
{
    printf("-------------\n");
}

void test()
{

}

void test1(void)
{

}

結果:this

hello world.
-------------
沒有返回值會報警告,雖然默認是整形。向已經void的參數傳入值,這個是錯誤的行爲,void test1(void)的用法就是spa

2,關於函數值傳遞和類型隱性轉換code

#include <stdio.h>

int add(int l, int r)
{
    return l + r;
}

int main(void)
{
    int a = 3, b = 5;
    int ret;
    double d1 = 3.14, d2 = 2.56;
    double dret;

    // C語言函數調用時, 參數是值傳遞(看着賦值)
    ret = add(a, b);
    printf("ret = %d\n", ret);    

    // 傳參過程當中發生隱式類型轉換    
    dret = add(d1, d2);
    printf("dret = %lf\n", dret);    

    return 0;
}

結果:blog

ret = 8
dret = 5.000000
強制轉換成雙精度。遞歸

3,變量不一樣的做用域ci

#include <stdio.h>

/*
 * scope (表如今編譯期 compiler time)
 *1. 全局做用域, 從變量聲明處開始, 到本文件結束.
 *2. 函數做用域, 從變量聲明處開始, 到函數結束.
 *3. 語句塊做用域, 從變量聲明處開始, 到語句塊結束.
 *
 *1. 同一做用域中, 變量不能重定義.
 *2. 內層做用域同名變量隱藏外層做用域同名變量.
 */

/*
 * lifetime (表如今運行期 runtime)
 *1. 全局變量/靜態變量在程序開始時存在, 一直到程序運行結束.
 *   存放在靜態存儲區(.data segment, .bss segment)
 *2. 局部變量在函數調用時開始存在, 函數調用結束後消失.
 *   存放在動態存儲區, 即運行棧(runtime stack)上.
 */

int a = 86;

void foo(void)
{
    int a = 76;
    printf("----foo---- a = %d\n", a);

    {
        int a = 36;
        printf("==foo==block, a = %d\n", a);
    }

    printf("----foo---- a = %d\n", a);
}

int main(void)
{
    printf("in main, a = %d\n", a);

    foo();

    return 0;
}

結果:作用域

in main, a = 86
----foo---- a = 76
==foo==block, a = 36
----foo---- a = 76
能夠看出,全局變量和局部變量同樣的話,以局部變量優先input

 

4,static變量編譯器

#include <stdio.h>

void foo(void)
{
    static int a;

    a++;
    printf("a = %d\n", a);
}

void bar(void)
{
    int a = 0;

    a++;
    printf("a = %d\n", a);
}

int main(void)
{
    int i;

    for (i = 0; i < 5; i++)
        foo();
    printf("-----------\n");
    for (i = 0; i < 5; i++)
        bar();

    return 0;
}

結果:

a = 1
a = 2
a = 3
a = 4
a = 5
-----------
a = 1
a = 1
a = 1
a = 1
a = 1
靜態局部變量是想讓局部變量在下次調用此函數時保留上次運行的結果。每次使用就是賦值。若是初始化不賦值的,編譯自動賦值0(數字型變量)空格(字符型變量)

自動變量就是不肯定的值了。register變量則是須要頻繁運算用到的變量能夠用,說白了就是使用寄存器節約時間。

 

5,多文件編譯例如兩個C文件。

5main.c

#include <stdio.h>

void foo(void);

int main(void)
{
    foo();

    return 0;
}

5foo.c

#include <stdio.h>

static void foo(void)
{
    printf("this is 5foo.c\n");
}

編譯方法:兩種編譯只是爲了讓人瞭解而已

will@will-Inspiron-N4010:~/c/3rd$ gcc -c 5main.c
will@will-Inspiron-N4010:~/c/3rd$ gcc -c 5foo.c
will@will-Inspiron-N4010:~/c/3rd$ gcc -o 5 5main.o 5foo.o
will@will-Inspiron-N4010:~/c/3rd$ ./5
this is 5foo.c
will@will-Inspiron-N4010:~/c/3rd$ gcc 5main.c 5foo.c
will@will-Inspiron-N4010:~/c/3rd$ ./a.out
this is 5foo.c

6,顯示完整語句執行過程

#include <stdio.h>

void foo(void)
{
    printf("foo");
}

void bar(void)
{
    printf("bar --> ");
    foo();
    printf(" <<= bar");
}

int main(void)
{
    printf("main --> ");
    bar();
    printf(" <<= main");

    putchar('\n');

    return 0;
}

結果:

will@will-Inspiron-N4010:~/c/3rd$ ./a.out
main --> bar --> foo <<= bar <<= main
7,遞歸應用

#include <stdio.h>

unsigned add(unsigned n)
{
    if (n == 1)
        return 1;
    return n + add(n - 1);
}

unsigned add_recursive(unsigned n)
{
    unsigned tmp;
    if (n == 1)
    {
        printf("這是第 %d 層返回.\n", n);    
        return 1;
    }

    printf("這是第 %d 層調用.\n", n);
    tmp = n + add_recursive(n - 1);

    printf("這是第 %d 層返回.\n", n);
    return tmp;
}

int main(void)
{
    unsigned n;

    printf("pls input n: ");
    scanf("%d", &n);

    printf("1 + 2 + ... + %d = %d\n", n, add_recursive(n));

    return 0;
}

結果:

pls input n: 5
這是第 5 層調用.
這是第 4 層調用.
這是第 3 層調用.
這是第 2 層調用.
這是第 1 層返回.
這是第 2 層返回.
這是第 3 層返回.
這是第 4 層返回.
這是第 5 層返回.
1 + 2 + ... + 5 = 15
層層深刻,又從中間層層跑出。又一個來回。

8,使用遞歸求解的斐波那契數列

#include <stdio.h>

unsigned fibonacci(unsigned n)
{
    if (n == 1)
        return 1;
    if (n == 2)
        return 1;

    return fibonacci(n - 1) + fibonacci(n - 2);
}

unsigned fibo_sum(unsigned n)
{
    if (n == 1)
        return 1;

    return fibonacci(n) + fibo_sum(n - 1);
}

int main(void)
{
    unsigned n;

    printf("input n: ");
    scanf("%d", &n);

    printf("第 %d 項: %d\n", n, fibonacci(n));    
    printf("前 %d 項和: %d\n", n, fibo_sum(n));

    return 0;
}

結果:

input n: 6
第 6 項: 8
前 6 項和: 20
1  1  2  3  5  8

9,兩個C文件編譯的變量的用法

9main.c

#include <stdio.h>

int gvar_main1 = 36;
int gvar_main2 = 48;

int foo(int, int);

int main(void)
{
    int ret;

    ret = foo(gvar_main1, gvar_main2);    

    printf("ret = %d\n", ret);

    return 0;
}

9foo.c

int gvar_foo1 = 66;
int gvar_foo2 = 88;

int add(int l, int r)
{
    return l + r;
}

int foo(int l, int r)
{
    return gvar_foo1 + gvar_foo2 - add(l, r);
}

結果:

will@will-Inspiron-N4010:~/c/3rd$ gcc 9main.c 9foo.c
will@will-Inspiron-N4010:~/c/3rd$ ./a.out
ret = 70

結果就是C文件函數的變量互不通用,編譯器連接的是函數

相關文章
相關標籤/搜索