将数组替换为 C 中的另一个数组

发布于 2024-12-14 15:08:02 字数 576 浏览 1 评论 0原文

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

typedef struct _test {
   float value;
} test;

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

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

我认为这行不通,而且它甚至无法编译。但是,这让我很感兴趣。是否可以在复制数据的同时将 10 个数组的大小增加到 20?

Objective-C

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

@interface Object : NSObject {
    test struct1;
}

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

Out of pure curiosity, I started playing with array's in ways that I have never used before. I tried making a data structure array, and set it equal to another:

typedef struct _test {
   float value;
} test;

Simple enough struct, so I tried this:

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

I didn't think this would work, and it didn't even compile. But, this interests me a lot. Is it possible to take an array of 10 and increase the size to 20, while copying the data?

Objective-C

I am actually doing this with Objective-C, so I'd like to hear from the Objective-C people as well. I want to see if it is possible to change the size of struct1 in this file.

@interface Object : NSObject {
    test struct1;
}

Remember: This is only out of curiosity, so everything is open to discussion.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

梦巷 2024-12-21 15:08:02

其他与您的问题不完全相关但仍然有趣的事情是,虽然不能分配数组,但可以分配包含数组的结构可以

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;
}

Something else that is not exactly pertinent to your question but is interesting nonetheless, is that although arrays cannot be assigned to, structs containing arrays can be assigned to:

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 */

This also makes it possible to return fixed-length arrays of data from functions (since returning plain arrays is not allowed):

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

    return result;
}
幸福不弃 2024-12-21 15:08:02

正如其他人所说,这样分配的数组是静态的,并且不能调整大小。您必须使用指针(使用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));

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

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

As others have said, arrays allocated like that are static, and can not be resized. You have to use pointers (allocating the array with malloc or calloc) to have a resizable array, and then you can use realloc. You must use free to get rid of it (else you'll leak memory). In C99, your array size can be calculated at runtime when its allocated (in C89, its size had to be calculated at compile time), but can't be changed after allocation. In C++, you should use std::vector. I suspect Objective-C has something like C++'s vector.

But if you want to copy data between one array and another in C, use 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));

That'll only copy the first ten elements, of course, since struct1 is only ten elements long. You could copy the last ten (for example) by changing &struct2 to struct2+10 or &(struct2[10]). In C, of course, not running off the end of the array is your responsibility: memcpy does not check.

You can also you the obvious for loop, but memcpy will often be faster (and should never be slower). This is because the compiler can take advantage of every trick it knows (e.g., it may know how to copy your data 16 bytes at a time, even if each element is only 1 byte wide)

忆悲凉 2024-12-21 15:08:02

在 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
}

You can't do this in C with static arrays, but you can do it with dynamically allocated arrays. E.g.,

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
}
同展鸳鸯锦 2024-12-21 15:08:02

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

In C, I believe that's a good place to use the realloc function. However, it will only work with dynamically allocated arrays. There's no way to change the memory allocated to struct1 by the declaration test struct1[10];.

℡Ms空城旧梦 2024-12-21 15:08:02

在 C 语言中,数组是常量,您根本无法更改它们的值(即它们的地址),也无法调整它们的大小。

In C arrays are constants, you can't change their value (that is, their address) at all, and you can't resize them.

风追烟花雨 2024-12-21 15:08:02

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

test *struct1;

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

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

Clearly if you declare your array with a fixed size, test struct1[10] then it cannot be resized. What you need to do is to declare it as a pointer:

test *struct1;

Then you must use malloc to allocate the array and can use realloc to resize it whilst preserving the contents of the original array.

struct1 = malloc(10*sizeof(*struct1));
//initialize struct1 ...
test *struct2 = realloc(struct1, 20*sizeof(*struct1));
不打扰别人 2024-12-21 15:08:02

如果您使用的是 Objective C,您知道您可以使用 NSMutableArray,它会自动执行重新分配技巧来重新分配自身以存储您放入其中的对象数量,直至达到内存限制。

但你想用 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 可能会移动一个对象,除非您更正所有指针,否则这在语义上是不正确的。

If you're using Objective C, you know you can just use NSMutableArray, which automatically does the realloc trick to reallocate itself to store however many objects you put in it, up the limit of your memory.

But you're trying to do this with struct? What would that even mean? Suppose you increase the amount of memory available to struct1 in Object. It's still a struct with one member, and doesn't do anything more.

Is the idea to make Object be able to contain an expanded struct?

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

But then you still can't access reference normally, because it's not a known part of Object.

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

If you knew you had one of your modified objects, you could do

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

And also you could still presumably pass object2 to anything that expects an Object. It only has any chance of working if struct1 is the last member of Object, and don't mess with subclassing Object either.

Some variety of realloc trick might then work, but I don't think realloc in particular, because that's intended to be used on objects that are allocated with malloc, and the details of what C function is used to allocate objects in not exposed in Objective C, so you shouldn't assume it's malloc. If you override alloc then you might be able to make sure malloc is used.

Also you have to watch out for the fact that it's common in Objective C for more than one pointer to an object to exist. realloc might move an object, which won't be semantically correct unless you correct all the pointers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文