来自 ChatGPT 对第一题的解释: 1. **数组声明和初始化**: ```c int a[5] = {1, 2, 3, 4, 5}; ``` 这行代码声明了一个包含 5 个整数的数组 `a`,并将其初始化为 1, 2, 3, 4, 5 。 2. **指针初始化**: ```c int *p = &a + 1; ``` 这一行代码比较复杂。我们逐步解析: - `&a` 是数组 `a` 的地址。`&a` 的类型是 `int (*)[5]`,即指向一个包含 5 个整数的数组的指针。 - `&a + 1` 表示将指针 `&a` 向前移动一个单位,这里的单位是整个数组 `a` 的大小(即 5 个整数的大小)。因此,它指向的是数组 `a` 之后的内存位置。 - `&a + 1` 的类型仍然是 `int (*)[5]`。 - 将 `&a + 1` 赋值给 `int *p` 时发生了隐式转换。最终 `p` 指向的是紧跟在数组 `a` 之后的内存位置。 总结来说,`p` 指向的是数组 `a` 结束之后的那块内存位置。 为了更好地理解这一点,我们来看一下内存布局: ``` 地址 值 0x1000 1 (a[0]) 0x1004 2 (a[1]) 0x1008 3 (a[2]) 0x100C 4 (a[3]) 0x1010 5 (a[4]) 0x1014 ? (p 指向这里) ``` 在这里,`p` 指向地址 `0x1014`,也就是在 `a[4]` 之后的内存位置。 ### 访问 `p` 在这种情况下访问 `*p` 是未定义行为,因为它指向的是数组 `a` 结束之后的那块内存位置。 你是否需要更多关于指针运算的信息,或者对这个代码有其他具体的问题?
关于第一题, 联想后面的 I2C 和 TCP, 表面上是指针, 实际是通过 offset 快速定位. 通信协议里经常用 offset 取特定信息 .https://zh.wikipedia.org/zh-cn/IPv4 但是 &a + 1 这种写法, vc++ 能过? 这么多年, linux 下从来没见过这种写法, 请 Linux 开发的面试官们手留情, 别误导青少年了. https://ibb.co/K7Lr73v
@basncy 我很同意你的第一点,面试官应该是想考察通过 offset 快速定位的知识点,但是感觉题没出好 hh 第二点的话,我刚刚试了在 gcc 7.5 下还是可以编译通过,但是会报 warning 了。
只说第一题哈,严格来说是不应该通过编译(或者说不鼓励写)的。 关键在于 (&a + 1)。指针的加法运算仅对「指向数组元素的指针」有定义,而 a 显然不是一个数组元素。所以 &a+1 的定义是依赖编译器实现的。 在连续的虚拟地址空间下,才能理想地认为 &a+1 代表 a 向后 5 个 sizeof(int) 字节的位置,然后再减 1 得到指向 a[4] 的指针。刻板地说,这题如果不加上这样那样的假设,那就是回答不了的。