用C中的另一个数组替换数组

时间:2011-11-08 22:15:06

标签: objective-c c arrays

出于纯粹的好奇心,我开始以我从未使用过的方式玩数组。我尝试制作数据结构数组,并将其设置为另一个数组:

typedef struct _test {
   float value;
} test;

足够简单struct,所以我尝试了这个:

test struct1[10];
test struct2[20];
struct1 = struct2;

我认为这不会起作用,甚至没有编译。但是,这让我很感兴趣。是否可以采用10的数组并将大小增加到20,同时复制数据?

目标C

我实际上是用Objective-C做的,所以我也想听听Objective-C的人。我想看看是否可以更改此文件中struct1的大小。

@interface Object : NSObject {
    test struct1;
}

记住:这只是出于好奇,所以一切都可以讨论。

7 个答案:

答案 0 :(得分:3)

其他与您的问题不完全相关但有趣的是,虽然无法分配数组,但包含数组的结构可以分配给:

struct test
{
    float someArray[100];
};


struct test s1 = { /* initialise with some data*/ };
struct test s2 = { /* initialise with some other data */ };

s1 = s2; /* s1's array now contains contents of s2's array */

这也可以从函数返回固定长度的数据数组(因为不允许返回普通数组):

struct test FunctionThatGenerates100Floats(void)
{
    struct test result;
    for (int i = 0; i < 100; i++)
        result.someArray[i] = randomfloat();

    return result;
}

答案 1 :(得分:2)

您不能在C中使用静态数组执行此操作,但您可以使用动态分配的数组执行此操作。例如,

float *struct1, *struct2, *struct3;
if(!(struct1 = malloc(10 * sizeof(float))) { 
  // there was an error, handle it here
}
if(!(struct2 = realloc(struct1, 20 * sizeof(float))) {
  // there was an error, handle it here
  // struct1 will still be valid
}
if(!(struct3 = reallocf(struct2, 40 * sizeof(float))) {
  // there was an error, handle it here
  // struct2 has been free'd
}

答案 2 :(得分:2)

正如其他人所说,像这样分配的数组是静态的,无法调整大小。您必须使用指针(使用malloccalloc分配数组)以获得可调整大小的数组,然后您可以使用realloc。你必须使用free来摆脱它(否则你会泄漏内存)。在C99中,您的数组大小可以在运行时计算(在C89中,其大小必须在编译时计算),但在分配后无法更改。在C ++中,您应该使用std::vector。我怀疑Objective-C有类似C ++的向量。

但是如果要在C中复制一个数组和另一个数组之间的数据,请使用memcpy

/* void *memcpy(void *dest, const void *src, size_t n)
   note that the arrays must not overlap; use memmove if they do */
memcpy(&struct1, &struct2, sizeof(struct1));

当然,那只会复制前十个元素,因为struct1只有十个元素长。您可以通过将&struct2更改为struct2+10&(struct2[10])来复制最后十个(例如)。当然,在C中,不负责运行数组的末尾是你的责任:memcpy不检查。

你也可以使用明显的for循环,但memcpy通常会更快(而且永远不会慢)。这是因为编译器可以利用它所知道的每一个技巧(例如,它可能知道如何一次复制16个字节的数据,即使每个元素只有1个字节宽)

答案 3 :(得分:1)

在C中,我相信这是使用realloc功能的好地方。但是,它只适用于动态分配的数组。没有办法通过声明struct1更改分配给test struct1[10];的内存。

答案 4 :(得分:1)

在C数组中是常量,你根本不能改变它们的值(即它们的地址),你也无法调整它们的大小。

答案 5 :(得分:1)

显然,如果您使用固定大小test struct1[10]声明数组,则无法调整其大小。你需要做的是将它声明为一个指针:

test *struct1;

然后你必须使用malloc来分配数组,并且可以使用realloc来调整它的大小,同时保留原始数组的内容。

struct1 = malloc(10*sizeof(*struct1));
//initialize struct1 ...
test *struct2 = realloc(struct1, 20*sizeof(*struct1));

答案 6 :(得分:1)

如果你正在使用Objective C,你知道你可以使用NSMutableArray,它会自动执行realloc技巧来重新分配自己以存储你放入其中的许多对象,超出你的记忆限制。

但你是想用struct做这件事吗?这甚至意味着什么?假设您增加了Object中struct1可用的内存量。它仍然是一个包含一个成员的结构,并且不再执行任何操作。

是否要使Object能够包含扩展的结构?

typedef struct _test2 {
    float value;
    NSObject *reference;
} test2;

但是你仍然无法正常访问reference,因为它不是Object的已知部分。

Object *object2;
...
NSLog(@"%@", object2.struct1.reference); // does not compile

如果你知道你有一个修改过的对象,你可以做

Object *object2;
...
NSLog(@"%@", ((test2)(object2.struct1)).reference);

而且你仍然可以将object2传递给任何需要Object的东西。如果struct1是Object的最后一个成员,它只有任何工作机会,并且不要乱用子类化Object。

然后可能会有各种各样的realloc技巧,但是我不认为realloc特别是因为它打算用于分配了malloc的对象,以及用于分配对象的C函数的细节。在Objective C中暴露,所以你不应该假设它是malloc。如果覆盖alloc,那么您可以确保使用malloc。

此外,您必须注意这样一个事实:在Objective C中,对于存在多个对象的指针,这种情况很常见。 realloc可能会移动一个对象,除非你纠正所有指针,否则这个对象在语义上是不正确的。