C语言之指针与数组

1,193 阅读4分钟

在C语言中,数组名就是数组首元素的地址,它是一个常量。所以我们可以使用指针来操作数组

指针遍历数组

void iterateArray() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    // 指针p指向arr[0]的地址
    int *p = arr;   // 等同于:int *p = &arr[0]
    int len = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < len; i++) {
        printf("%d\n", p[i]);
    }
}

从上图可以看出,每个元素的地址相差4个字节,所以p指针加一个int类型的大小就是下一个元素的地址。

void iterateArray2() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    // 指针p指向arr[0]的地址
    int *p = arr;   // 等同于:int *p = &arr[0]
    int len = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < len; i++) {
        // p + i 表示地址变成了:p + i * sizeof(int)
        printf("地址为:%p\n", p + i);
        printf("地址对应的值:%d\n", *(p + i));
    }
}

指针++与指针+n的区别

指针+n只是把当前的地址变成了某个元素的地址,指针并没有移动;而指针++或指针--是把指针向右或者向左进行移动。

void pointerOperate() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    // 指针p指向arr[0]的地址
    int *p = arr;   // 等同于:int *p = &arr[0]

    // 将数组第三个元素的值改为300
    *(p + 2) = 300; // {1, 2, 300, 4, 5, 6, 7, 8, 9, 10}

    // 将p指向数组第二个元素的地址,并将值改为200
    p++;
    *p = 200;       // {1, 200, 300, 4, 5, 6, 7, 8, 9, 10}

    // 以当前p所在地址,改变内存地址为 2 * sizeof(arr[0])的值为400
    *(p + 2) = 400; // {1, 200, 300, 400, 5, 6, 7, 8, 9, 10}

    // 将p指向数组第9个元素的地址,将元素值改为900
    p = &arr[8];
    *p = 900;       // {1, 200, 300, 400, 5, 6, 7, 8, 900, 10}

    // 将p指向数组第8个元素的地址,并将元素值改为800
    p--;
    *p = 800;       // {1, 200, 300, 400, 5, 6, 7, 800, 900, 10}

    // 将p指向数组第1个元素的地址,并将元素值改为101
    p = &arr[0];
    *p += 100;      // {101, 200, 300, 400, 5, 6, 7, 800, 900, 10}

    // 野指针,不允许操作未知空间的值
//    p = 100;
//    *p = 100;


    int len = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < len; i++) {
        printf("%d\n", arr[i]);
    }


}

指针数组与多级指针

指针数组,顾名思义,就是数组元素都是地址。

int a = 1, b = 2, c = 3;
int *arr[] = {&a, &b, &c};
*arr[0] = 4;
printf("%d\n", a);

当数组元素为字符串时,也就变成了二级指针。

char *strArr[] = {"Tom", "Lucy", "Lily"};
// 数组的元素是字符串,而字符串是一个字符数组
char *p = strArr[0];
// 用一个二级指针指向一级指针
char **pp = strArr;
printf("%X\n", **pp);

多级指针

在内存中,每一个变量都有其对应的地址,指向这个地址的就是一个指针变量。既然指针变量也是一个变量,那么它也有其自己的地址,那么指向这个提针变量地址的称为多级指针。

int d = 4;
int *p1 = &d;
int **p2 = &p1;
int ***p3 = &p2;
int ****p4 = &p3;
// n级指针的关系
*p4 = p3 = &p2;
**p4 = *p3 = p2 = &p1;
***p4 = **p3 = *p2 = p1 = &d;
****p4 = ***p3 = **p2 = *p1 = d;

指针练习

  • 在字符串中查找字符
char *charInStr(char *src, char target) {
    while (*src) {
        if (*src == target) {
            return src;
        }
        src++;
    }
    return NULL;
}
  • 字符串反转

用两个指针变量,一个指向头,一个指向尾,头指针++,尾指针--

void strReverse(char *str) {
    char *head = str;
    char *tail = &str[strlen(str) - 1];
    while (head < tail) {
        char temp = *head;
        *head = *tail;
        *tail = temp;
        head++;
        tail--;
    }
}
  • 去除字符串首尾空字符
char *trimStrBlank(char *str) {
    char *head = str;
    char *tail = str + strlen(str) - 1;
    while (*head == ' ' && head < tail) {
        head++;
    }
    while (*tail == ' ' && tail > head) {
        tail--;
    }
    // 去掉空字符后需加上字符串结束标志
    *(tail + 1) = '\0';
    return head;
}
  • 在字符串中查找字符串

遍历源字符串,将源字符串中的每一个字符与目标字符进行一一比对。

char *strInStr2(char *src, char *target) {
    char *res = NULL;
    char *temp = target;
    while (*src) {
    	  // 记录src遍历到的位置
        res = src;
        // 相等情况
        while (*src && *temp == *src) {
            temp++;
            src++;
        }
        if (!*temp) {
            // 说明target字符全部匹配成功
            return res;
        } else {
            // 重置temp,进行下一轮比较
            temp = target;
        }
        src++;
    }
    return NULL;
}
  • 字符串拼接
void strConcat(char *src, char *target) {
    while (*src) {
        src++;
    }
    while (*target) {
        *src = *target;
        src++;
        target++;
    }
    // src已经++到最后一个位置了,
    // 所以添加字符串结束标志时不需要+1了
    *src = '\0';
}
  • 字符串排序
void strSort(char **arr, int len) {
    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len - i - 1; j++) {
            if (**(arr + j) > **(arr + j + 1)) {
                char *temp = *(arr + j);
                *(arr + j) = *(arr + j + 1);
                *(arr + j + 1) = temp;
            }
        }
    }
}

int main() {
	// 这是一个指针数组
    char *strArr[] = {"dog", "cat", "boy", "ago"};
    int len = sizeof(strArr) / sizeof(strArr[0]);
    // 所以这个函数的第一个参数是一个二级指针
    strSort(strArr, len);
    for (int i = 0; i < len; ++i) {
        printf("%s\n", strArr[i]);	// ago  boy     cat     dog
    }
    return EXIT_SUCCESS;
}