C语言-指针

本文最后更新于:1 年前

注意点

  • 指针的加减操作会移动一个数据类型的长度

    1
    2
    y = ++*px; //px的内容加上1之后赋给y,++*px相当于++(*px)
    y = *px++; //相当于y=*(px++)
  • sizeof(数组名)才能获取数组长度,sizeof(数组指针)得到指针本身长度。sizeof返回无符号数,类型size_t

    1
    2
    3
    4
    5
    int a[5]={0};
    int *p = a;

    sizeof(p)/sizeof(int) --> 1
    sizeof(a)/sizeof(int) --> 5

数组名作为函数参数时都是指针

以下三种形式都传递了数组指针,在函数内部无法通过这个指针获得数组长度,都要作为指针变量对待。(数组名退化为一级指针)

1
2
3
4
5
6
7
8
9
int max(int intArr[6], int len){

}
int max(int intArr[], int len){

}
int max(int *intArr, int len){

}

空指针应初始化为NULL(注意大小写)

char *str = NULL;

NULL 是在stdio.h中定义的一个宏 #define NULL ((void *)0)void *表示指针指向的数据的类型是未知的,一般在后续使用时进行强制类型转换

用指针作为函数返回值时

需要注意,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针请尽量不要指向这些数据

指针数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
char *lines[5] = {             //lines占用内存 = 4(指针本身长度) *5
"COSC1283/1284",
"Programming",
"Techniques",
"is",
"great fun"
};
char *str1 = lines[1];
char *str2 = *(lines + 3);
char c1 = *(*(lines + 4) + 6);
char c2 = (*lines + 5)[5];
char c3 = *lines[0] + 2;
printf("str1 = %s\n", str1);
printf("str2 = %s\n", str2);
printf(" c1 = %c\n", c1);
printf(" c2 = %c\n", c2);
printf(" c3 = %c\n", c3);

输出结果为:

str1 = Programming
str2 = is
c1 = f
c2 = 2
c3 = E

  • lines[1]:它是一个指针,指向字符串string1,即string1 的首地址。
  • *(lines + 3):lines + 3 为数组中第 3 个元素的地址,*(lines + 3) 为第 3 个元素的值,它是一个指针,指向字符串 string3。
  • *(*(lines + 4)+ 6)*(lines + 4) + 6 == lines[4] + 6 == string4 + 6,表示字符串 string4 中第 6 个字符的地址,即 f 的地址,所以 ((lines + 4) + 6) 就表示字符 f。
  • (*lines +5)[5]*lines + 5 为字符串 string0 中第 5 个字符的地址,即 2 的地址,(*lines+5)[5]等价于*(*lines+5+5),表示第10个字符,即 2。
  • *lines[0]+2:lines[0] 为字符串 string0 中第 0 个字符的地址,即 C 的地址;*lines[0] 也就表示第 0 个字符,即字符 C。字符与整数运算,首先转换为该字符对应的 ASCII 码,然后再运算,所以 *lines[0] + 2 = 67 + 2 = 69,69 对应的字符为 E。

二维数组指针

1
2
3
4
5
6
7
int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
int (*p)[4] = a; //p占用内存 = 4 (指针本身长度)
printf("%d\n", sizeof(*(p+1)));

a+i == p+i
a[i] == p[i] == *(a+i) == *(p+i)
a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j) 可用于遍历数组
  • 括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int[4],这正是 a 所包含的每个一维数组的类型。

  • [ ]的优先级高于*,( )是必须要加的,如果赤裸裸地写作int *p[4],那么应该理解为int *(p[4]),p 就成了一个指针数组,而不是二维数组指针

  • p指向数组 a 的开头,也即第 0 行;p+1前进一行,指向第 1 行。

  • *(p+1)表示取地址上的数据,也就是整个第 1 行数据。注意是一行数据,是多个数据,不是第 1 行中的第 0 个元素

  • *(p+1)+1表示第 1 行第 1 个元素的地址。因为*(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof、& 一起使用时才表示整个数组出现在表达式中就会被转换为指向数组第 0 个元素的指针。

  1. *(*(p+1)+1)表示第 1 行第 1 个元素的值。很明显,增加一个 * 表示取地址上的数据。