C语言中复制数组并移除末尾元素:能否用指针截断实现?
C语言数组截取复制的实现方案
首先明确:你没法通过动态修改指针让数组“仅延伸到最后一个元素之前”。原因是:
- C语言中数组的长度是编译期固定的(变长数组VLA除外,但VLA的长度也只能在声明时确定,后续无法修改);
- 指针仅存储内存地址,不携带数组长度信息,编译器无法识别你所谓的“截断后数组”的边界,直接这样操作会导致越界访问、
sizeof计算错误等未定义行为; - 你提到的地址计算
&A - sizeof(A[0])是错误的:&A是指向整个数组的指针,类型为int (*)[n](假设A是int数组),和元素指针的步长不同,正确的最后一个元素前的地址应该是A + (len_A - 1)(len_A是A的元素个数)。
下面给出两种合规的实现方式:
1. 实际复制元素到新数组B
这是最安全的方案,将A的前len_A-1个元素复制到独立的数组B中:
#include <stdio.h> #include <string.h> int main() { int A[] = {1, 2, 3, 4, 5}; int len_A = sizeof(A) / sizeof(A[0]); int B[len_A - 1]; // B的大小为A的元素个数减1 // 复制前len_A-1个元素 memcpy(B, A, (len_A - 1) * sizeof(int)); // 验证输出 for (int i = 0; i < len_A - 1; i++) { printf("%d ", B[i]); } return 0; }
- 优势:B是独立数组,修改B不会影响A,访问无越界风险,完全符合C标准。
2. 用指针+长度模拟截断数组
如果不想复制内存,仅需以截断方式访问A,可通过指针配合长度变量模拟:
#include <stdio.h> int main() { int A[] = {1, 2, 3, 4, 5}; int len_A = sizeof(A) / sizeof(A[0]); int *B = A; // B指向A的首元素 int len_B = len_A - 1; // 截断后的元素个数 // 访问时通过len_B控制边界 for (int i = 0; i < len_B; i++) { printf("%d ", B[i]); } return 0; }
- 注意:这里的
B是指针而非数组,不能用sizeof(B)获取长度,必须单独维护len_B;修改B[i]会直接修改A[i],需谨慎操作。
补充:用变长数组(VLA)实现类型化的截断数组
如果你需要让编译器识别截断后数组的长度,可以使用C99引入的变长数组:
#include <stdio.h> #include <string.h> int main() { int A[] = {1, 2, 3, 4, 5}; int len_A = sizeof(A) / sizeof(A[0]); int B[len_A - 1]; // 声明变长数组,长度为len_A-1 memcpy(B, A, (len_A - 1) * sizeof(int)); printf("B的字节大小:%zu\n", sizeof(B)); // 会正确输出(len_A-1)*sizeof(int) return 0; }
- 限制:变长数组只能在函数内部声明,且部分老编译器可能不支持C99标准。
内容的提问来源于stack exchange,提问作者theotechnic
相关产品推荐
相关产品推荐

