C语言程序设计-10 指针

	指针是C语言中广泛使用的一种数据类型。运用指针编程是C语言最主要的风格之一。

利用指针变量可以表示各种数据结构;能很方便地使用数组和字符串;并能象汇编语言一样
处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。学习指针是
学习C语言中最重要的一环,能否正确理解和使用指针是我们是否掌握C语言的一个标志。
同时,指针也是C语言中最为困难的一部分,在学习中除了要正确理解基本概念,还必须要
多编程,上机调试。只要作到这些,指针也是不难掌握的。

10.1 地址指针的基本概念

在计算机中,所有的数据都是存放在存储器中的。一般把存储器中的一个字节称为一个
内存单元,不同的数据类型所占用的内存单元数不等,如整型量占 2 个单元,字符量占 1
个单元等,在前面已有详细的介绍。为了正确地访问这些内存单元,必须为每个内存单元编
上号。根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号也叫做地址。
既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指
针。 内存单元的指针和内存单元的内容是两个不同的概念。 可以用一个通俗的例子来说明
它们之间的关系。我们到银行去存取款时, 银行工作人员将根据我们的帐号去找我们的存
款单, 找到之后在存单上写入存款、取款的金额。在这里,帐号就是存单的指针, 存款数
是存单的内容。对于一个内存单元来说,单元的地址即为指针,其中存放的数据才是该单元
的内容。在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指
针变量的值就是某个内存单元的地址或称为某内存单元的指针。
在这里插入图片描述
图中,设有字符变量 C,其内容为“K”(ASCII 码为十进制数 75),C 占用了 011A 号单元
(地址用十六进数表示)。设有指针变量 P,内容为 011A,这种情况我们称为 P 指向变量 C,
或说 P 是指向变量 C 的指针。
严格地说,一个指针是一个地址,是一个常量。而一个指针变量却可以被赋予不同的指
针值,是变量。但常把指针变量简称为指针。为了避免混淆,我们中约定:“指针”是指地
址,是常量,“指针变量”是指取值为地址的变量。定义指针的目的是为了通过指针去访问
内存单元。
既然指针变量的值是一个地址,那么这个地址不仅可以是变量的地址,也可以是其它数
据结构的地址。在一个指针变量中存放一个数组或一个函数的首地址有何意义呢? 因为数
组或函数都是连续存放的。通过访问指针变量取得了数组或函数的首地址,也就找到了该数
组或函数。这样一来,凡是出现数组,函数的地方都可以用一个指针变量来表示,只要该指
针变量中赋予数组或函数的首地址即可。这样做,将会使程序的概念十分清楚,程序本身也
精练,高效。在C语言中,一种数据类型或数据结构往往都占有一组连续的内存单元。 用
“地址”这个概念并不能很好地描述一种数据类型或数据结构,而“指针”虽然实际上也是一
个地址,但它却是一个数据结构的首地址,它是“指向”一个数据结构的,因而概念更为清
楚,表示更为明确。 这也是引入“指针”概念的一个重要原因。

10.2 变量的指针和指向变量的指针变量

10.2.1定义一个指针变量

10.2.2指针变量的引用

【例 10.1】

#include <stdio.h>

main()
{
    int a, b;
    int *pointer_1, *pointer_2;
    a = 100;
    b = 10;
    pointer_1 = &a;
    pointer_2 = &b;
    printf("%d,%d\n", a, b);
    printf("%d,%d\n", *pointer_1, *pointer_2);
}

【例 10.2】输入 a 和 b 两个整数,按先大后小的顺序输出 a 和 b。

#include <stdio.h>

main()
{
    int *p1, *p2, *p, a, b;
    scanf("%d,%d", &a, &b);
    p1 = &a;
    p2 = &b;
    if (a < b)
    {
        p = p1;
        p1 = p2;
        p2 = p;
    }
    printf("\na=%d,b=%d\n", a, b);
    printf("max=%d,min=%d\n", *p1, *p2);
}

10.2.3指针变量作为函数参数

【例 10.3】题目同例 10.2,即输入的两个整数按大小顺序输出。今用函数处理,而且用指
针类型的数据作函数参数。

#include <stdio.h>

swap(int *p1, int *p2)
{
    int temp;
    temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}
main()
{
    int a, b;
    int *pointer_1, *pointer_2;
    scanf("%d,%d", &a, &b);
    pointer_1 = &a;
    pointer_2 = &b;
    if (a < b)
        swap(pointer_1, pointer_2);
    printf("\n%d,%d\n", a, b);
}

【例 10.4】请注意,不能企图通过改变指针形参的值而使指针实参的值改变。

#include <stdio.h>

swap(int *p1, int *p2)
{
    int *p;
    p = p1;
    p1 = p2;
    p2 = p;
}
main()
{
    int a, b;
    int *pointer_1, *pointer_2;
    scanf("%d,%d", &a, &b);
    pointer_1 = &a;
    pointer_2 = &b;
    if (a < b)
        swap(pointer_1, pointer_2);
    printf("\n%d,%d\n", *pointer_1, *pointer_2);
}

【例 10.5】输入 a、b、c3 个整数,按大小顺序输出。

#include <stdio.h>

swap(int *pt1, int *pt2)
{
    int temp;
    temp = *pt1;
    *pt1 = *pt2;
    *pt2 = temp;
}
exchange(int *q1, int *q2, int *q3)
{
    if (*q1 < *q2)
        swap(q1, q2);
    if (*q1 < *q3)
        swap(q1, q3);
    if (*q2 < *q3)
        swap(q2, q3);
}
main()
{
    int a, b, c, *p1, *p2, *p3;
    scanf("%d,%d,%d", &a, &b, &c);
    p1 = &a;
    p2 = &b;
    p3 = &c;
    exchange(p1, p2, p3);
    printf("\n%d,%d,%d \n", a, b, c);
}

10.2.4指针变量几个问题的进一步说明

【例 10.6】

#include <stdio.h>

main()
{
    int a = 5, *p = &a;
    printf("%d", *p);
}

【例 10.7】

#include <stdio.h>

main()
{
    int a = 10, b = 20, s, t, *pa, *pb; /*说明 pa,pb 为整型指针变量*/
    pa = &a;                            /*给指针变量 pa 赋值,pa 指向变量 a*/
    pb = &b;                            /*给指针变量 pb 赋值,pb 指向变量 b*/
    s = *pa + *pb;                      /*求 a+b 之和,(*pa 就是 a,*pb 就是 b)*/
    t = *pa * *pb;                      /*本行是求 a*b 之积*/
    printf("a=%d\nb=%d\na+b=%d\na*b=%d\n", a, b, a + b, a * b);
    printf("s=%d\nt=%d\n", s, t);
}

【例 10.8】

#include <stdio.h>

main()
{
    int a, b, c, *pmax, *pmin;        /*pmax,pmin 为整型指针变量*/
    printf("input three numbers:\n"); /*输入提示*/
    scanf("%d%d%d", &a, &b, &c);      /*输入三个数字*/
    if (a > b)
    {              /*如果第一个数字大于第二个数字...*/
        pmax = &a; /*指针变量赋值*/
        pmin = &b;
    } /*指针变量赋值*/
    else
    {
        pmax = &b; /*指针变量赋值*/
        pmin = &a;
    } /*指针变量赋值*/
    if (c > *pmax)
        pmax = &c; /*判断并赋值*/
    if (c < *pmin)
        pmin = &c;                            /*判断并赋值*/
    printf("max=%d\nmin=%d\n", *pmax, *pmin); /*输出结果*/
}

10.3 数组指针和指向数组的指针变量

10.3.1指向数组元素的指针

10.3.2通过指针引用数组元素

【例 10.9】输出数组中的全部元素。(下标法)

#include <stdio.h>

main()
{
    int a[10], i;
    for (i = 0; i < 10; i++)
        a[i] = i;
    for (i = 0; i < 5; i++)
        printf("a[%d]=%d\n", i, a[i]);
}

【例 10.10】输出数组中的全部元素。(通过数组名计算元素的地址,找出元素的值)

#include <stdio.h>

main()
{
    int a[10], i;
    for (i = 0; i < 10; i++)
        *(a + i) = i;
    for (i = 0; i < 10; i++)
        printf("a[%d]=%d\n", i, *(a + i));
}

【例 10.11】输出数组中的全部元素。(用指针变量指向元素)

#include <stdio.h>

main()
{
    int a[10], I, *p;
    p = a;
    for (i = 0; i < 10; i++)
        *(p + i) = i;
    for (i = 0; i < 10; i++)
        printf("a[%d]=%d\n", i, *(p + i));
}

【例 10.12】

#include <stdio.h>

main()
{
    int a[10], i, *p = a;
    for (i = 0; i < 10;)
    {
        *p = i;
        printf("a[%d]=%d\n", i++, *p++);
    }
}

几个注意的问题:

  1. 指针变量可以实现本身的值的改变。如 p++是合法的;而 a++是错误的。因为 a 是数组
    名,它是数组的首地址,是常量。
  2. 要注意指针变量的当前值。请看下面的程序。
    【例 10.13】找出错误。
#include <stdio.h>

main()
{
    int *p, i, a[10];
    p = a;
    for (i = 0; i < 10; i++)
        *p++ = i;
    for (i = 0; i < 10; i++)
        printf("a[%d]=%d\n", i, *p++);
}

【例 10.14】改正。

#include <stdio.h>

main()
{
    int *p, i, a[10];
    p = a;
    for (i = 0; i < 10; i++)
        *p++ = i;
    p = a;
    for (i = 0; i < 10; i++)
        printf("a[%d]=%d\n", i, *p++);
}
  1. 从上例可以看出,虽然定义数组时指定它包含 10 个元素,但指针变量可以指到数组以
    后的内存单元,系统并不认为非法。
  2. p++,由于++和同优先级,结合方向自右而左,等价于*(p++)。
  3. (p++)与(++p)作用不同。若 p 的初值为 a,则*(p++)等价 a[0],*(++p)等价 a[1]。
  4. (*p)++表示 p 所指向的元素值加 1。
  5. 如果 p 当前指向 a 数组中的第 i 个元素,则
    *(p–)相当于 a[i–];
    *(++p)相当于 a[++i];
    *(–p)相当于 a[–i]。

10.3.3数组名作函数参数

同样,指针变量的值也是地址,数组指针变量的值即为数组的首地址,当然也可作为函
数的参数使用。
【例 10.15】

#include <stdio.h>

float aver(float *pa);
main()
{
    float sco[5], av, *sp;
    int i;
    sp = sco;
    printf("\ninput 5 scores:\n");
    for (i = 0; i < 5; i++)
        scanf("%f", &sco[i]);
    av = aver(sp);
    printf("average score is %5.2f", av);
}
float aver(float *pa)
{
    int i;
    float av, s = 0;
    for (i = 0; i < 5; i++)
        s = s + *pa++;
    av = s / 5;
    return av;
}

【例 10.16】将数组 a 中的 n 个整数按相反顺序存放。
算法为:将 a[0]与 a[n-1]对换,再 a[1]与 a[n-2] 对换……,直到将 a[(n-1/2)]与
a[n-int((n-1)/2)]对换。今用循环处理此问题,设两个“位置指示变量”i 和 j,i 的初值为
0,j 的初值为 n-1。将 a[i]与 a[j]交换,然后使 i 的值加 1,j 的值减 1,再将 a[i]与 a[j]
交换,直到 i=(n-1)/2 为止,如图所示。
在这里插入图片描述

#include <stdio.h>

void inv(int x[], int n) /*形参x是数组名*/
{
    int temp, i, j, m = (n - 1) / 2;
    for (i = 0; i <= m; i++)
    {
        j = n - 1 - i;
        temp = x[i];
        x[i] = x[j];
        x[j] = temp;
    }
    return;
}
main()
{
    int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2};
    printf("The original array:\n");
    for (i = 0; i < 10; i++)
        printf("%d,", a[i]);
    printf("\n");
    inv(a, 10);
    printf("The array has benn inverted:\n");
    for (i = 0; i < 10; i++)
        printf("%d,", a[i]);
    printf("\n");
}

对此程序可以作一些改动。将函数 inv 中的形参 x 改成指针变量。
【例 10.17】对例 10.16 可以作一些改动。将函数 inv 中的形参 x 改成指针变量。
程序如下:

#include <stdio.h>

void inv(int *x, int n) /*形参x为指针变量*/
{
    int *p, temp, *i, *j, m = (n - 1) / 2;
    i = x;
    j = x + n - 1;
    p = x + m;
    for (; i <= p; i++, j--)
    {
        temp = *i;
        *i = *j;
        *j = temp;
    }
    return;
}
main()
{
    int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2};
    printf("The original array:\n");
    for (i = 0; i < 10; i++)
        printf("%d,", a[i]);
    printf("\n");
    inv(a, 10);
    printf("The array has benn inverted:\n");
    for (i = 0; i < 10; i++)
        printf("%d,", a[i]);
    printf("\n");
}

执行结果

The original array:
3,7,9,11,0,6,7,5,4,2,
The array has benn inverted:
2,4,5,7,6,0,11,9,7,3,

【例 10.18】从 0 个数中找出其中最大值和最小值。
调用一个函数只能得到一个返回值,今用全局变量在函数之间“传递”数据。程序如下:

#include <stdio.h>

int max, min; /*全局变量*/
void max_min_value(int array[], int n)
{
    int *p, *array_end;
    array_end = array + n;
    max = min = *array;
    for (p = array + 1; p < array_end; p++)
        if (*p > max)
            max = *p;
        else if (*p < min)
            min = *p;
    return;
}
main()
{
    int i, number[10];
    printf("enter 10 integer umbers:\n");
    for (i = 0; i < 10; i++)
        scanf("%d", &number[i]);
    max_min_value(number, 10);
    printf("\nmax=%d,min=%d\n", max, min);
}

说明:

  1. 在函数 max_min_value 中求出的最大值和最小值放在 max 和 min 中。由于它们是全局,
    因此在主函数中可以直接使用。
  2. 函数 max_min_value 中的语句:
    max=min=*array;
    array 是数组名,它接收从实参传来的数组 numuber 的首地址。
    array 相当于(&array[0])。上述语句与 max=min=array[0];等价。
  3. 在执行 for 循环时,p 的初值为 array+1,也就是使 p 指向 array[1]。以后每次执行 p++,
    使 p 指向下一个元素。每次将*p 和 max 与 min 比较。将大者放入 max,小者放 min。
  4. 函数 max_min_value 的形参 array 可以改为指针变量类型。实参也可以不用数组名,而
    用指针变量传递地址。
    【例 10.19】程序可改为:
#include <stdio.h>

int max, min; /*全局变量*/
void max_min_value(int *array, int n)
{
    int *p, *array_end;
    array_end = array + n;
    max = min = *array;
    for (p = array + 1; p < array_end; p++)
        if (*p > max)
            max = *p;
        else if (*p < min)
            min = *p;
    return;
}
main()
{
    int i, number[10], *p;
    p = number; /*使p指向number数组*/
    printf("enter 10 integer umbers:\n");
    for (i = 0; i < 10; i++, p++)
        scanf("%d", p);
    p = number;
    max_min_value(p, 10);
    printf("\nmax=%d,min=%d\n", max, min);
}

【例 10.20】用实参指针变量改写将 n 个整数按相反顺序存放。

#include <stdio.h>

void inv(int *x, int n)
{
    int *p, m, temp, *i, *j;
    m = (n - 1) / 2;
    i = x;
    j = x + n - 1;
    p = x + m;
    for (; i <= p; i++, j--)
    {
        temp = *i;
        *i = *j;
        *j = temp;
    }
    return;
}
main()
{
    int i, arr[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}, *p;
    p = arr;
    printf("The original array:\n");
    for (i = 0; i < 10; i++, p++)
        printf("%d,", *p);
    printf("\n");
    p = arr;
    inv(p, 10);
    printf("The array has benn inverted:\n");
    for (p = arr; p < arr + 10; p++)
        printf("%d,", *p);
    printf("\n");
}

注意:main 函数中的指针变量 p 是有确定值的。即如果用指针变作实参,必须现使指针变
量有确定值,指向一个已定义的数组。
【例 10.21】用选择法对 10 个整数排序。

#include <stdio.h>

main()
{
    int *p, i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2};
    printf("The original array:\n");
    for (i = 0; i < 10; i++)
        printf("%d,", a[i]);
    printf("\n");
    p = a;
    sort(p, 10);
    for (p = a, i = 0; i < 10; i++)
    {
        printf("%d ", *p);
        p++;
    }
    printf("\n");
}
sort(int x[], int n)
{
    int i, j, k, t;
    for (i = 0; i < n - 1; i++)
    {
        k = i;
        for (j = i + 1; j < n; j++)
            if (x[j] > x[k])
                k = j;
        if (k != i)
        {
            t = x[i];
            x[i] = x[k];
            x[k] = t;
        }
    }
}

说明:函数 sort 用数组名作为形参,也可改为用指针变量,这时函数的首部可以改为:
sort(int *x,int n) 其他可一律不改。

10.3.4指向多维数组的指针和指针变量

【例 10.22】

#include <stdio.h>

main()
{
    int a[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    printf("%d,", a);
    printf("%d,", *a);
    printf("%d,", a[0]);
    printf("%d,", &a[0]);
    printf("%d\n", &a[0][0]);
    printf("%d,", a + 1);
    printf("%d,", *(a + 1));
    printf("%d,", a[1]);
    printf("%d,", &a[1]);
    printf("%d\n", &a[1][0]);
    printf("%d,", a + 2);
    printf("%d,", *(a + 2));
    printf("%d,", a[2]);
    printf("%d,", &a[2]);
    printf("%d\n", &a[2][0]);
    printf("%d,", a[1] + 1);
    printf("%d\n", *(a + 1) + 1);
    printf("%d,%d\n", *(a[1] + 1), *(*(a + 1) + 1));
}

【例 10.23】

#include <stdio.h>

main()
{
    int a[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    int(*p)[4];
    int i, j;
    p = a;
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 4; j++)
            printf("%2d ", *(*(p + i) + j));
        printf("\n");
    }
}

10.4 字符串的指针指向字符串的针指变量

10.4.1字符串的表示形式

C 语言中,可以用两种方法访问一个字符串。
1) 用字符数组存放一个字符串,然后输出该字符串。
【例 10.24】

#include <stdio.h>

main()
{
    char string[] ="I love China !";
    printf("%s\n", string);
}

【例 10.25】

#include <stdio.h>

main()
{
    char *string ="I love China !";
    printf("%s\n", string);
}

【例 10.26】输出字符串中 n 个字符后的所有字符。

#include <stdio.h>

main()
{
    char *ps = "this is a book";
    int n = 10;
    ps = ps + n;
    printf("%s\n", ps);
}

【例 10.27】在输入的字符串中查找有无‘k’字符。

#include <stdio.h>

main()
{
    char st[20], *ps;
    int i;
    printf("input a string:\n");
    ps = st;
    scanf("%s", ps);
    for (i = 0; ps[i] != '\0'; i++)
        if (ps[i] == 'k')
        {
            printf("there is a 'k' in the string\n");
            break;
        }
    if (ps[i] == '\0')
        printf("There is no 'k' in the string\n");
}

【例 10.28】本例是将指针变量指向一个格式字符串,用在 printf 函数中,用于输出二维
数组的各种地址表示的值。但在 printf 语句中用指针变量 PF 代替了格式串。 这也是程序
中常用的方法。

#include <stdio.h>

main()
{
    static int a[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    char *PF;
    PF = "%d,%d,%d,%d,%d\n";
    printf(PF, a, *a, a[0], &a[0], &a[0][0]);
    printf(PF, a + 1, *(a + 1), a[1], &a[1], &a[1][0]);
    printf(PF, a + 2, *(a + 2), a[2], &a[2], &a[2][0]);
    printf("%d,%d\n", a[1] + 1, *(a + 1) + 1);
    printf("%d,%d\n", *(a[1] + 1), *(*(a + 1) + 1));
}

**【例 10.29】本例是把字符串指针作为函数参数的使用。要求把一个字符串的内容复制到另
一个字符串中,并且不能使用 strcpy 函数。函数 cprstr 的形参为两个字符指针变量。pss
指向源字符串,pds 指向目标字符串。注意表达式:(pds=pss)!=`\0’的用法。

#include <stdio.h>

cpystr(char *pss, char *pds)
{
    while ((*pds = *pss) != '\0')
    {
        pds++;
        pss++;
    }
}
main()
{
    char *pa = "CHINA", b[10], *pb;
    pb = b;
    cpystr(pa, pb);
    printf("string a=%s\nstring b=%s\n", pa, pb);
}

【例 10.30】简化后的程序如下所示。

#include <stdio.h>

cpystr(char *pss, char *pds)
{
    while (*pds++ = *pss++)
        ;
}
main()
{
    char *pa = "CHINA", b[10], *pb;
    pb = b;
    cpystr(pa, pb);
    printf("string a=%s\nstring b=%s\n", pa, pb);
}

10.4.2使用字符串指针变量与字符数组的区别

10.5 函数指针变量

【例 10.31】本例用来说明用指针形式实现对函数调用的方法。

#include <stdio.h>

int max(int a, int b)
{
    if (a > b)
        return a;
    else
        return b;
}

int main() // 注意main函数的返回类型应当是int,同时建议显式返回0表示程序正常结束
{
    int (*pmax)(int, int); // 指针的声明应明确参数类型,虽然在某些编译器上可省略,但明确指定更佳
    int x, y, z;
    pmax = max; // 此处无需更改
    printf("input two numbers:\n");
    scanf("%d%d", &x, &y);
    z = (*pmax)(x, y); // 此处无需更改
    printf("maximum=%d", z);

    return 0; // 添加return语句
}

10.6 指针型函数

【例 10.32】本程序是通过指针函数,输入一个 1~7 之间的整数,输出对应的星期名。

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

char *day_name(int n); // 添加函数原型声明

int main() // 建议明确指定main函数的返回类型为int
{
    int i;
    printf("input Day No:\n");
    scanf("%d", &i);
    if (i < 0)
        exit(1);
    printf("Day No:%2d-->%s\n", i, day_name(i));
    return 0; // 主函数正常结束应返回0
}

char *day_name(int n)
{
    static char *name[] = {"Illegal day",
                           "Monday",
                           "Tuesday",
                           "Wednesday",
                           "Thursday",
                           "Friday",
                           "Saturday",
                           "Sunday"};
    return ((n < 1 || n > 7) ? name[0] : name[n]);
}

10.7 指针数组和指向指针的指针

10.7.1指针数组的概念

【例 10.33】通常可用一个指针数组来指向一个二维数组。指针数组中的每个元素被赋予
二维数组每一行的首地址,因此也可理解为指向一个一维数组。

#include <stdio.h>


main()
{
    int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int *pa[3] = {a[0], a[1], a[2]};
    int *p = a[0];
    int i;
    for (i = 0; i < 3; i++)
        printf("%d,%d,%d\n", a[i][2 - i], *a[i], *(*(a + i) + i));
    for (i = 0; i < 3; i++)
        printf("%d,%d,%d\n", *pa[i], p[i], *(p + i));
}

【例 10.34】指针数组作指针型函数的参数。在本例主函数中,定义了一个指针数组 name,
并对 name 作了初始化赋值。其每个元素都指向一个字符串。然后又以 name 作为实参调用
指针型函数 day_name,在调用时把数组名 name 赋予形参变量 name,输入的整数 i 作为第二
个实参赋予形参 n。在 day_ name 函数中定义了两个指针变量 pp1 和 pp2,pp1 被赋予 name[0]
的值(即name),pp2 被赋予 name[n]的值即(name+ n)。由条件表达式决定返回 pp1 或 pp2
指针给主函数中的指针变量 ps。最后输出 i 和 ps 的值。

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

main()
{
    static char *name[] = {"Illegal day",
                           "Monday",
                           "Tuesday",
                           "Wednesday",
                           "Thursday",
                           "Friday",
                           "Saturday",
                           "Sunday"};
    char *ps;
    int i;
    char *day_name(char *name[], int n);
    printf("input Day No:\n");
    scanf("%d", &i);
    if (i < 0)
        exit(1);
    ps = day_name(name, i);
    printf("Day No:%2d-->%s\n", i, ps);
}
char *day_name(char *name[], int n)
{
    char *pp1, *pp2;
    pp1 = *name;
    pp2 = *(name + n);
    return ((n < 1 || n > 7) ? pp1 : pp2);
}

【例 10.35】输入 5 个国名并按字母顺序排列后输出。现编程如下:

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

main()
{
    void sort(char *name[], int n);
    void print(char *name[], int n);
    static char *name[] = {"CHINA", "AMERICA", "AUSTRALIA",
                           "FRANCE", "GERMAN"};
    int n = 5;
    sort(name, n);
    print(name, n);
}
void sort(char *name[], int n)
{
    char *pt;
    int i, j, k;
    for (i = 0; i < n - 1; i++)
    {
        k = i;
        for (j = i + 1; j < n; j++)
            if (strcmp(name[k], name[j]) > 0)
                k = j;
        if (k != i)
        {
            pt = name[i];
            name[i] = name[k];
            name[k] = pt;
        }
    }
}
void print(char *name[], int n)
{
    int i;
    for (i = 0; i < n; i++)
        printf("%s\n", name[i]);
}

10.7.2指向指针的指针

【例 10.36】使用指向指针的指针。

#include <stdio.h> // 只保留必需的头文件

int main() // 明确main函数的返回类型为int
{
    // 定义一个字符串数组
    char *names[] = {
        "Follow me",
        "BASIC",
        "Great Wall",
        "FORTRAN",
        "Computer design" // 修正拼写错误:desighn -> design
    };

    // 使用指针遍历并打印数组中的每个字符串
    for (int index = 0; index < 5; ++index) // 使用更直观的变量名,并使用++运算符置于变量后,这是一种常见的编码风格
    {
        char **pointer = names + index; // 明确指出此指针用于指向数组中的字符串
        printf("%s\n", *pointer);
    }

    return 0; // 程序成功执行完毕,返回0
}

【例 10.37】一个指针数组的元素指向数据的简单例子。

#include <stdio.h>

main()
{
    static int a[5] = {1, 3, 5, 7, 9};
    int *num[5] = {&a[0], &a[1], &a[2], &a[3], &a[4]};
    int **p, i;
    p = num;
    for (i = 0; i < 5; i++)
    {
        printf("%d\t", **p);
        p++;
    }
}

10.7.3main 函数的参数

【例 10.38】

#include <stdio.h>

main(int argc, char *argv)
{
    while (argc-- > 1)
        printf("%s\n", *++argv);
}

10.8 有关指针的数据类型和指针运算的小结

10.8.1有关指针的数据类型的小结

在这里插入图片描述

10.8.2指针运算的小结

现把全部指针运算列出如下:

  1. 指针变量加(减)一个整数:
    例如:p++、p–、p+i、p-i、p+=i、p-=i
    一个指针变量加(减)一个整数并不是简单地将原值加(减)一个整数,而是将该指针
    变量的原值(是一个地址)和它指向的变量所占用的内存单元字节数加(减)。
  2. 指针变量赋值:将一个变量的地址赋给一个指针变量。
    p=&a; (将变量 a 的地址赋给 p)
    p=array; (将数组 array 的首地址赋给 p)
    p=&array[i]; (将数组 array 第 i 个元素的地址赋给 p)
    p=max; (max 为已定义的函数,将 max 的入口地址赋给 p)
    p1=p2; (p1 和 p2 都是指针变量,将 p2 的值赋给 p1)
    注意:不能如下:
    p=1000;
  3. 指针变量可以有空值,即该指针变量不指向任何变量:
    p=NULL;
  4. 两个指针变量可以相减:如果两个指针变量指向同一个数组的元素,则两个指针变量值
    之差是两个指针之间的元素个数。
  5. 两个指针变量比较:如果两个指针变量指向同一个数组的元素,则两个指针变量可以进
    行比较。指向前面的元素的指针变量“小于” 指向后面的元素的指针变量。

10.8.3void 指针类型

ANSI 新标准增加了一种“void”指针类型,即可以定义一个指针变量,但不指定它是指向
哪一种类型数据。

  • 35
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 您好,我是AI语言助手,以下是对您的回复: 20201022-成信大-c语言程序设计-20201学期《c语言程序设计b》是一门面向大学生的C语言程序设计课程,主要教授C语言的基础知识和编程技巧,包括数据类型、运算符、流程控制语句、函数、指针、数组、结构体等内容。通过本课程的学习,学生可以掌握C语言的基本语法和编程思想,提高编程能力和解决问题的能力,为以后的编程学习和工作打下坚实的基础。 ### 回答2: 20201学期的《c语言程序设计b》是一个深入学习C语言的课程,教授的是C语言的高级应用。在本次课程中,学生将会进一步学习C语言的语法、程序设计思路以及具体的编码实践。 首先,学生将会学习C语言中的函数、指针、结构体、联合体、枚举等高级概念。这些概念是C语言面向对象编程中至关重要的概念,也是学生在日后编写复杂程序时所必须了解的内容。此外,在学习这些概念的同时,学生还将学习如何使用宏定义和预编译指令来进一步优化程序性能。 其次,学生将会进行具体的编码实践,包括基于C语言的数据结构设计和实现、字符串处理、文件操作、网络编程等等。这些项目和实践将会提供给学生大量的机会来将所学的概念应用到具体的场景中,帮助学生更深入地理解C语言的应用。 此外,学生还将参加课堂讨论、代码评审等活动,通过这些活动来提高自己的编程能力、代码质量和团队协作能力。教师也将会给学生提供详细的反馈,帮助他们改善自己的问题和提高自己的能力。 总之,《c语言程序设计b》是一门非常重要的课程,对于学生日后从事计算机编程工作具有非常重要的意义。通过学习这门课程,学生将会大幅提高自己的编程能力、透彻理解C语言并将其应用到实际工作中。 ### 回答3: 成信大-20201学期《c语言程序设计b》是一门针对深入学习C语言的高级课程,内容涵盖了高级数据结构、算法设计、动态内存分配、文件操作等等。 在这门课程中,学生将通过实践和理论学习,掌握C语言的高级编程技巧和策略。课程的重点之一是高级数据结构,包括链表、树、哈希表、图等等,学生将深入理解数据结构的实现和应用。 除此之外,课程还将涉及算法设计和分析,学生将学习如何设计出高效的算法,并进行时间和空间复杂度分析。动态内存分配和文件操作也是这门课程的重点,这些技术对于C语言程序设计来说非常重要。 学生在课程中还将开展实践项目,以实现理论学习。通过项目实践,学生将在实际中应用学到的技术,发现其中存在的问题并解决。 总之,成信大-20201学期《c语言程序设计b》是一门非常高级的、面向深度学习的课程。通过系统学习和实践的方式,学生将深入掌握C语言的高级编程技巧。这门课程对于想要深入学习C语言的学生来说是非常重要的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值