这就是 C 语言难的原因。这是一个错误:您需要分配(end-start+1) 项目并在循环中使用<=。尝试改写成这样:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Track {
char* color;
} Track;
Track * subArray(Track* arr, int start, int end){
assert(end > start);
const int size = 1 + end - start;
printf("Allocating %d items\n", size);
Track* t = malloc(sizeof(Track)*size);
for(int i=start; i <= end; ++i) {
printf("at %d fetching %d\n", i-start, i);
t[i-start] = arr[i];
}
return t;
}
int main() {
Track *track = malloc(sizeof(Track) * 7);
track[0].color = "red";
track[1].color = "orange";
track[2].color = "yellow";
track[3].color = "blue";
track[4].color = "indigo";
track[5].color = "green";
track[6].color = "violet";
Track *sub = subArray(track, 3, 5);
printf("%s\n", sub[0].color);
printf("%s\n", sub[1].color);
printf("%s\n", sub[2].color);
}
编译运行:
$ cc -g -W -Wall a.c && ./a.out
Allocating 3 items
at 0 fetching 3
at 1 fetching 4
at 2 fetching 5
blue
indigo
green
请注意,我在这里复制了char* 指针的值。这可能会导致更多令人困惑的内容,以防万一您考虑复制我的代码(我刚刚起草了一些可以说明问题的内容)。
更新
您正在使用包容性索引。然而,在 C 中,指定起始索引和长度是很常见的。许多标准库函数都这样做,这是您最有可能在生产代码中看到的。一个原因可能是它更容易推理。在您的情况下,代码将是
Track* subArray(Track* arr, const size_t start, const size_t length) {
Track* t = malloc(sizeof(Track) * length);
for (size_t i = 0; i < length; ++i)
t[i] = arr[i + start];
return t;
}
相应的调用将是
Track *sub = subArray(track, 3, 3);
在我看来,这不仅更好看;它更简单,更容易理解。
另一件常见的事情是复制指针而不是整个结构。这将取决于您的代码和数据结构的组织方式。在这种情况下,在指针数组的末尾使用哨兵值来标记其结束是很常见的:这通常是一个 NULL 指针。
继续练习并继续阅读其他人的代码,您很快就会发现 C 习语和编程风格,它们会让您的生活变得更轻松!