C 错题集

数组和指针 (二)

  • 数组下标 ‘’[]” 内可以是表达式 但下标值不可超过初始定义范围

a[1>2][!1] “1>2”为假,等于0 “!1” :1为真 ,非1 就是假,故为0 所以前式是求a[0] [0]

2117a30ff603cbc377df19f2c676fd5b

  • 这里先解释 int *q[] 这里表示的是把整个数组定义为指针

​ 即可这样定义

1.指针指向变量

1
2
3
4
5
6
7
// 定义指针数组,包含3个整型指针
int *q[3];

// 让每个指针指向不同的整型变量
q[0] = &a;
q[1] = &b;
q[2] = &c;

2.指针指向数组

1
2
3
4
5
6
7
// 也可以指向数组
int arr1[2] = {1, 2};
int arr2[3] = {3, 4, 5};

q[0] = arr1; // 指向第一个数组
q[1] = arr2; // 指向第二个数组
q[2] = &a; // 指向单个变量

b61e61c7cc8e7015ffac42fdb8e63ced

这里主要想讲解D选项:

1
2
3
4
5
6
7
//a是二维数组,把首地址a[i]重新看成一个指针常量,即:
a[4]=n n[10]=a[4][10]
/*这里a[4]退化为int*(即指向改行的第一个元素)
p是int*指针
q是长度为4的数组,每个元素都是int*(即每个元素都是指针)*/
在D中 a的类型是int(*)[10](指向含有10int的数组的指针),而p是int*,类型不同,故错

再插入一个知识点 指向指针的数组和指针数组的区别

  • int(*)[10] -指向指针的数组
1
int(*ptr)[10];
  • 含义:一个指针,指向包含10个整数的数组
  • 类型:指向数组的指针
  • 内存大小sizeof(ptr)指针的大小(通常4或8字节)
  • 指针运算ptr + 1 跳过整个数组(10 * sizeof(int) 字节)

示例:

1
2
3
4
5
6
int arr[10] = {0};
int (*ptr)[10] = &arr; // 指向整个数组

printf("%p\n", ptr); // 数组起始地址
printf("%p\n", ptr + 1); // 跳过40字节(假设int为4字节)
//(相当于一个内存条放了一个数组,ptr是代表这个内存的地址,加一后即跳过这个内存条---跳过这个数组)

int[10] - 指针数组*

1
int* arr[10];
  • **含义:**一个包含10个整型指针的数组
  • **类型:**指针数组
  • **内存大小:*sizeof(arr) = 10 * sizeof(int)(通常40或80字节)

相当于有十个内存条,每个内存条放一个整型指针,若此时“arr+1”那则是跳过第一个内存条到下一个内存条中,则一次跳过4个字节

  • **指针运算:**arr + 1 跳过一个指针的大小(通常4或8字节)

示例:

1
2
3
4
5
6
7
8
int a = 1, b = 2, c = 3;
int* ptrArr[10]; // 包含10个int指针的数组

ptrArr[0] = &a;
ptrArr[1] = &b;
ptrArr[2] = &c;

printf("%d\n", *ptrArr[0]); // 输出: 1

6c4801e23ef623bb23b7dcb420127bcc

定义并初始化数组

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

数组 a 按行填充(换成一维数组来思考):

  • a[0]: {1, 2}
  • a[1]: {3, 4}
  • a[2]: {5, 6}

p 是指针数组,每个元素是 int* 类型

1
2
p[0] = a[1];
//a[1]是第二行的数组名,会退为指向该行首元素的指针,即&a[1][0]

所以p[0]指向 (为指针)a[1] [0]

1
*(p[0] + 1)
  • p[0] 指向 a [1] [0](地址)

  • p[0] + 1 指向下一个 int,即 a[1] [1](值为 4)

  • 解引用得到 a[1] [1] 的值 4

    所以 ***(p[0] + 1)** 代表数组元素 a[1][1]。

81dc1ec46143cfeefe5141be939604f3

1
2
3
int c[4][5]; //二维数组
int (*p)[5]; //指向数组的指针
p=c; //p指向二维数组c的第一行

注意题目是说要正确引用数组c的元素 不是地址or指针

1
2
3
4
A.p+1  //p=&c[0] p+1=&c[1](是指向第二行的指针,类型是int(*)[5],并不是数组元素,而是指向一行的指针。)
B.*(p[0]+2) //p[0]=&c[0][0] p[0]+2=&c[0][2],然后再解引
C.*(p+1)+3 //p+1=&c[1](第二行数组名, 退化为 int*,指c[1][0])
D.*(p+3) //p+3 是 &c[3](第四行),*(p+3) 是 c[3](第四行数组名,类型 int[5] 退化为 int*)