从0学起的C语言笔记(9、指针1)

从0学起的C语言笔记(9、指针1)



指针与数组

概念:数组

再说数组之前就先简单说说数组,
数组是若干个相同类型的变量在内存中有序存储的集合,就是数组。

概念:指针

提供一种以符号形式使用地址的方法。因为计算机的硬件指令非常依赖地址,而指针在某种程度上把程序猿想要传达的指令以更接近机器的方式表达。因此指针是高效的,尤其是指针可以更有效率的处理数组。数组表示法,就是变相的使用指针。
所以想要阅读本章的首要前提是了解数组可点击转到自己写的数组的笔记。

示例与分析

#include<stdio.h>
#define SIZE 4
int main(){
    short dates[SIZE];
    short * pti;
    short index;
    double bills[SIZE];
    double * ptf;
    pti = datas;
    ptf = bills;
    printf("%s23s %18s\n","short","double");
    for(index = 0; index < SIZE; index++)
        printf("数组 + %d;%10p %10p", index, pti + index, ptf + index);
    return 0;
}

请添加图片描述在我们的系统中,short为2字节,double为8字节。在C中,指针加1指的是增加1个存储单元,对于数组而言,这意味着后加一个元素为下个元素的地址。这就是为什么需要声明指针指向元素的类型。

现在可以清楚地定义指向 int 的指针,指向 float 的指针,以及指向其他数据对象的指针。

  • 指针的值为他指向的对象的地址。地址的表示方式依赖于计算机内部的硬件。许多计算机 (包括PC和Macintosh [Mac] [Mac采用的Power PC芯片是RISC(精简指令集)芯片,而PC机采用的多为CISC(复杂指令集)芯片。Power PC是通过多管线操控配合超标量指令集来运行的,而CISC芯片则是采用单线程方式来运行的]) 都是按字节编址,内存中的每一个字节都是按照顺序编号
  • 在指针前加使用 * 运算符可以得到给指针的所指向的对象的值。
  • 指针加1,指针的值递增他所指向数值的大小

注意要点

dates + 2 == &dates[2];   //相同的地址
*(dates + 2) == dates[2]; //相同的值

C语言的语言标准在表述数组时确实借用了数组。也就是说,定义 ar[n] 的意思是 * (ar+n) 。可以认为 * (ar+n) 的意思是 “到内存ar的位置,然后移动n个单位,检索存储在哪里的值”。

注意:不要混淆* (dates + 2) 和 * dates + 2。间接运算符*的优先级高于+ ,所以* dates + 2 相当于 *(dates)+2。

函数、数组、指针

示例与分析

需求:

假设需要编写一个处理数组的函数,该函数返回数组中的所有元素之和,待处理的名为 marbles 的 int 类型的数组。

total = sum(marbles);     //可能的函数调用

那么函数的原型是什么?数组名是函数的该数组的首地址,所以实际的参数应该是marbles是一个存储 int 类型的地址,,所以应该付给他一个 int 类型的指针:

int sum(int *ar);      //对应的函数原型

示例:

#include<stdio.h>
#define SIZE 10
int sum(int * ar, int n);
int main()
{
    int marbles[SIZE] = {20, 10, 0, 12, 23, 42, 14, \
    45, 54, 76};
    long answer;
    
    answer = sum(marbles, SIZE);
    printf("数组之和为:%ld\n", answer);
    printf("数组占用的存储为:%ld", sizeof marbles);
}
int sum(int * ar, int n)
{
    int i;
    int total = 0;
    for(i = 0; i < n; i++)
    {
        total += ar[i];
    }
    return total;
}

优化:

函数要处理数组必须要知道从何开始,从何结束。sum函数使用一个指针形参表示数组的开始,用一个整数形参表示待处理数组的元素个数。但是这并不是给函数传递必须信息的唯一办法。还可以传递两个指针,一个表示数组的开始,另一个表示数组的结束。

指针形参

根据优化方案,我们需要了解指针的形参这个问题,下面看示例。

示例与分析

示例

#include<stdio.h>
#define SIZE 10
int sum(int * start, int * end);
int main()
{
    int marbles[SIZE] = {20, 10, 0, 12, 23, 42, 14, \
    45, 54, 76};
    long answer;
    answer = sum(marbles, marbles + SIZE);
    printf("数组之和为:%ld\n", answer);
    printf("数组占用的存储为:%ld", sizeof marbles);
}
int sum(int * start, int * end)
{
    int total = 0;
    while(start < end){
        total += *start;
        start++;
    }
    return total;
}

指针 start 开始指向 marbles 数组的首元素所以赋值表达式 total += *start 把首元素(20)加给total。然后,表达式 start++ 递增指针变量 start,使其指向下一个元素。因为 start 是指向 int 的指针,start++ 递增1相当于递增 int 类型的大小。

注意要点

可以把循环体压缩为一行的代码

total += *start; 
start++;
total += *start++; 

一元运算符*和++运算优先级相同,但是结合律是从右到左,所以 start++是先求值,在取*start。也就是说,指针start先递增再指向。

使用后缀(start++而不是++start)意味着先把指针指向的值加到total上再递增指针。如果使用*++start,则顺序相反,先自增,再使用指针指向的值。

所以 虽然*start++比较常见,但是为了便于理解一般写为 *(start++)

对形参使用const

ANSI C 提供了一种预防错误修改不该修改的数据的手段。如果函数的意图不是为了修改数组中的内容,那么在函数原型和函数定义中声明形式参数时应使用关键字 const

int sum(const int * start, const int * end);
int sum(const int * start, const int * end)
{
    int total = 0;
    while(start < end){
        total += *start;
        start++;
    }
    return total;
}

示例与分析

#include<stdio.h>
#define SIZE 5
int show_array(const double ar[], int n);
int mult_array(double ar[], int n ,double mult);
int main()
{
    double dip[SIZE] = {20.0, 12.3, 21.3, 43.3, 46.2};
    printf("初始化数组为:");
    show_array(dip,SIZE);
    mult_array(dip,SIZE,2.5);
    printf("修改后数组为:");
    show_array(dip,SIZE)
}
int show_array(const double ar[], int n){
    int i;
    for(i = 0; i < n; i++)
    {
        printf("%8.3f",ar[i]);
    }
    putchar('\n');
}
int mult_array(double ar[], int n, double mult)
{
    int i;
    for (int i = 0; i < n; ++i) {
        ar[i] *= mult;
    }
}

注意要点

该程序中两个函数的返回值都是void,所以虽然mult_arrat()函数更新了dip数组的值,但是没有使用return机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值