《C语言教程》17章 数组作参数


一、数组作参数后的长度

数组作参数时,其后面的长度毫无意义,应该改成不定义长度的数组。作为参数时,数组将自己降级为指针。下面例子中,sizeof(arr)取到的是arr地址的长度,等于4。而主程序中sizeof(num)应该是12。


#include <stdio.h>

int subFunc(int arr[3]);

int main(void)
{
    int x, len;
    num[] ={10, 20, 30};

    //取数组的长度
    len = sizeof(num) / sizeof(int);
    printf("main中的数组长度:%dn\n", len);

    //让数组的每一个元素加1
    for (i=0; i<len; i++) {
        printf("%3d", ++num[i]);  //++num[i]是先加后显示
    }
    subFunc(num);    //调用子函数

    //再次显示数组内容
    printf("\nmain中的数组:\n");
    for(i=0; i<len; i++) {
        printf("%3d", num[i]);    //只有num[0]发生了改变
    }
    printf("\n");

    return 0;
}

int subFunc(int arr[3])   //将数组改成指针,结果一样    int subFunc(int *arr)
{                         //若用数组也应该不定义长度    int subFunc(int arr[])
    int i, len ;

    //取数组的长度
    len = sizeof(arr) / sizeof(int);
    printf("subFunc中的数组长度:%d\n",len);

    //让数组的每一个元素加1
    for(i=0; i<len; i++) {        //其实并没有循环3次
        printf("%3d", ++arr[i]);  //只循环了1次
    }                             //如果将len改成3,便可以达到预期效果
    printf("\n");

    return ;
}

二、数组作参数的一般方法

数组作参数时等同于指针作参数,因此一般写成指针。但指针是不知道长度的,所以一般作法是增加一个参数来传递长度。


#include <stdio.h>

void subFunc(int *, int);  //这样申明是正确的

int main(void)
{
    int i, len ;
    int num[] = {10, 20, 30};

    subFunc(num, 3);    //调用子函数

    //显示数组内容
    printf("\nmain中调用后显示:");
    for (i=0; i<3; i++) {
        printf("%3d", num[i]);
    }
    printf("\n");

    return 0;
}

void subFunc(int *arr, int size)   //数组和长度同时传递是比较好的做法
{
    int i ;

    for(i=0; i<size; i++) {
        printf("%3d", ++arr[i]);
    }

    return ;
}

还有一种做法,将数组长度申明为常量,无论何处直接使用常量。注意:申明的后面不能加分号。


#include <stdio.h>

#define LENGTH 3     //注意:不能加分号“;”

void subFunc(int *);

int main(void)
{
    int i ;
    int num[] = {10, 20, 30};

    subFunc(num);    //调用子函数

    //显示数组内容
    printf("\nmain中调用后显示:");
    for (i=0; i<LENGTH; i++) {      //直接使用常量
        printf("%3d", num[i]);
    }
    printf("\n");

    return 0;
}

void subFunc(int *arr)
{
    int i ;

    for(i=0; i<LENGTH; i++) {      //直接使用常量
        printf("%3d", ++arr[i]);
    }

    return ;
}

三、防止空指针

指针作参数时,调用的地方有二种情况,一是用数组名,二是用指针变量名。数组名是已经分配了空间的地址,直接使用没有问题。指针的话,可能分配了空间,也有可能是空指针、野指针、未初始化的指针。


#include <stdio.h>

#define LENGTH 3

void subFunc(int *);

int main(void)
{
    int *num = NULL;

    subFunc(num);    //调用子函数

    return 0;
}

void subFunc(int *arr)
{
    int i ;

    if (arr == NULL) {        //对指针要经常判断,这一点非常重要
        printf("数据为空。\n");
        return ;
    }

    for(i=0; i<LENGTH; i++) {      //直接使用常量
        printf("%3d", ++arr[i]);
    }

    return ;
}

野指针、未初始化的指针并不为空,需要编程人员自己控制,下一章是指针经常出错的地方,请认真阅读。

四、sizeof错了吗

下面的程序是测试你对本章的理解,如果你不看结果图而能写出答案,说明你掌握得不错。


#include <stdio.h>

void func(char *);

int main(void)
{
    char s[] = "abcd\0efghij";
    char *t  = "ABCD\0EFGHIJ";
    char *ps = s + 5;
    char *pt = t + 5;

    //不看结果,你能算出答案吗?
    printf("main: strlen=%d, sizeof=%d\n", strlen(s), sizeof(s));
    func(s);
    printf("ps: %s\n", ps);

    printf("main: strlen=%d, sizeof=%d\n", strlen(t), sizeof(t));
    func(t);
    printf("pt: %s\n", pt);

    return 0;
}

void func(char *str)
{
    printf("func: strlen=%d, sizeof=%d\n", strlen(str), sizeof(str));

    return ;
}