数组学习

本文详细介绍了C语言中的指针与数组概念,包括传值与传址调用的区别、数组名与地址的关系、数组指针及指针数组的概念,并通过实例展示了函数指针的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传值调用与传址调用

指针是变量,因此可以声明指针参数 ,因此可以声明指针参数

当一个函数体内部需要改变实参的值,则需要使用指针参数 ,则需要使用指针参数

函数调用时实参值将复制到形参

指针适用于复杂数据类型作为参数的函数中

数组地址与数组名

数组名代表数组首元素的地址

数组的地址需要用取地址符&才能得到

数组首元素的地址值与数组的地址值相同

数组首元素的地址与数组的地址是两个不同的概念

数组名可以看做一个常量指针

数组名“指向”的是内存中数组首元素的起始位置

在表达式中数组名只能作为右值使用

只有在下列场合中数组名不能看做常量指针

              数组名作为sizeof操作符的参数 数组名作为&运算符的参数

a为数组是数组首元素的地址

&a为整个数组的地址

a和&a的意义不同其区别在于指针运算

C语言中,数组作为函数参数时 ,数组作为函数参数时,编译器将 其编译成对应的指针

void f(int a[])<=>void f(int* a);                    void f(int a[5])<=>void f(int* a);

一般情况下,当定义的函数中有数组参数时 ,当定义的函数中有数组参数时,需要定 义另一个参数来标示数组的大小

C语言中通过typedef为数组类型重命名                 typedef type(name)[size];

数组类型: typedef int(AINT5)[5];                          typedef float(AFLOAT10)[10];

数组定义: AINT5 iArray;              AFLOAT10 fArray

数组指针

数组指针用于指向一个数组

数组名是数组首元素的起始地址,但并不是数组的起始地址 

通过将取地址符&作用于数组名可以得到数组的起始地址 

可通过数组类型定义数组指针: ArrayType* pointer;

也可以直接定义:type (*pointer)[n];    pointer为数组指针变量名    type为指向的数组的类型    n为指向的数组的大小

#include <stdio.h>
typedef float(AFLOAT10)[10];
int main()
{
    float fArray[10];
    AFLOAT10* pf = &fArray;
    int i = 0;
    for(i=0; i<10; i++)
    {
        (*pf)[i] = i;
    }

指针数组

指针数组是一个普通的数组

指针数组中每个元素为一个指针

数组指针的定义:type* pArray[n]; type*为数组中每个元素的类型 pArray为数组名 n为数组大小 float

#include <stdio.h>
#include <string.h>

int lookup_keyword(const char* key, const char* table[], const int size)
{
    int ret = -1;
    
    int i = 0;
    
    for(i=0; i<size; i++)
    {
        if( strcmp(key, table[i]) == 0 )
        {
            ret = i;
            break;
        }
    }
    
    return ret;
}

#define DIM(a) (sizeof(a)/sizeof(*a))

int main()
{
    const char* keyword[] = {
            "do",
            "for",
            "if",
            "register",
            "return",
            "switch",
            "while",
            "case",
            "static"
    };
    
    printf("%d\n", lookup_keyword("return", keyword, DIM(keyword)));
    printf("%d\n", lookup_keyword("main", keyword, DIM(keyword)));
}

数组指针本质上是一个指针

数组指针指向的值是数组的地址

指针数组本质上是一个数组

指针数组中每个元素的类型是指针

一维数组名代表数组首元素的地址 int a[5] a的类型为int*

二维数组名同样代表数组首元素的地址 int m[2][5] m的类型为int(*)[5]

void f(int a[5])<=>void f(int a[])<=>void f(int* a);

void g(int a[3][3])<=> void g(int a[][3])<=>void g(int (*a)[3]);

指针数组:int* a[5]   指针的指针:int** a

结论:

1. 二维数组名可以看做是指向数组的常量指针

2. 二维数组可以看做是一维数组

3. 二维数组中的每个元素都是同类型的一维数组

函数的类型由返回值,参数类型和参数个数共同决定 例:

int add(int i, int j)的类型为int(int, int)

C语言中通过typedef为函数类型重命名 typedef type name(parameter list)

例: typedef int f(int, int); typedef void p(int);

函数指针

函数指针用于指向一个函数

函数名是执行函数体的入口地址

可通过函数类型定义函数指针: FuncType* pointer;

也可以直接定义:type (*pointer)(parameter list);

pointer为函数指针变量名   type为指向函数的返回值类型    parameter list为指向函数的参数类型列表

回调函数

#include <stdio.h>

typedef int(*FUNCTION)(int);

int g(int n, FUNCTION f)
{
    int i = 0;
    int ret = 0;
    
    for(i=1; i<=n; i++)
    {
        ret += i*f(i);
    }
    
    return ret;
}

int f1(int x)
{
    return x + 1;
}

int f2(int x)
{
    return 2*x - 1;
}

int f3(int x)
{
    return -x;
}

int main()
{
    printf("x * f1(x): %d\n", g(3, f1));
    printf("x * f2(x): %d\n", g(3, f2));
    printf("x * f3(x): %d\n", g(3, f3));
}

 

回调函数带参数
int add(int a,int b);  
int sub(int a,int b);  
  
void functionchoose(int a, int b, int (*pf)(int, int));  
  
  
int main()  
{  
    int a1=3,a2=4;  
    functionchoose(a1,a2,add);  
    functionchoose(a1,a2,sub);  
    return 0;  
}  
  
int add(int a, int b)  
{  
    printf("add function \n");  
    return a+b;  
  
}  
  
int sub(int a, int b)  
{  
    printf("sub function \n");  
    return a-b;  
}  
  
void functionchoose(int a,int b,int (*pf)(int,int))  
{  
    printf("the result is %d \n",(*pf)( a, b));  
  
}  

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值