假设我将 struct 定义为

typedef struct worker{
  char name[20];
  int age;
} worker

然后我创建一个长度为20的数组,

worker *business;
business = malloc(20 * sizeof(worker));

是否有任何"自然"(即已经在语言中实现)的方法可以从这样的数组中获得"age"元素的子数组?

我在想一些

business.age

其中business.agebusiness的每个元素的年龄的整数数组?

推荐答案

数组中的age个 struct 字段不会形成连续的内存区域.内存中的布局类似于此:

              business[0]                          business[1]
[ 20 bytes of name | 4 bytes of age ][ 20 bytes of name | 4 bytes of age][ 20...

您的年龄由名称数组分隔.由于C中的数组必须是连续的、没有间隙的内存区域,因此不可能只引用年龄的"数组".但是,您可以使用for循环轻松地遍历年龄,或者编写函数/定义宏以访问特定索引处的年龄:

int get_age_at_index(worker* arr, int idx) {
    return arr[idx].age;
}
// OR
#define GET_AGE_AT_INDEX(arr, idx) (arr[idx].age)

这可能会允许使用与访问数组元素类似的语义,如果您所追求的是:

int my_age = get_age_at_index(business, 5);
// OR
int my_other_age = GET_AGE_AT_INDEX(business, 3);

如果您对复制数据没有意见,您可以只为20个整数分配一个数组,并从每个 struct 中复制年龄:

int ages[20] = { 0 };
for(int i; i < 20; i++) {
    ages[i] = business[i].age;
}

EDIT

当您在C中有一个指向数组开头的指针(如worker* business)并将其作为数组索引时

business points to the beginning of array:
[ worker struct 0    ][ worker struct 1    ][ worker struct 2    ]
^                     ^                     ^
  0 * sizeof(worker)    1 * sizeof(worker)    2 * sizeof(worker) <-- offsets from the beginning of array

如果我们使指针等于第一个 struct 内存中age个成员的地址,但将其转换为worker*:

worker* my_hacky_pointer = (worker*) &(business[0].age);

将其增加1实际上会将其移动sizeof(worker),因为这是指针的类型.因此,它将移动到数组下一个元素的age个成员.如果我们随后将此指针转换回int并取消对其的引用*(int*) (my_hacky_pointer + 1),我们将得到索引1处age字段的值.

完整示例来源:

#include <stdio.h>
#include <stdlib.h>

typedef struct worker{
  char name[20];
  int age;
} worker;

int main() {
        worker* business = malloc(20 * sizeof(worker));

        business[0].age = 5;
        business[1].age = 6;
        business[2].age = 99;
        business[3].age = 66;
        business[4].age = 78;

        worker* my_hacky_pointer = (worker*) &(business[0].age);
        printf("my age: %d\n", *(int*) (my_hacky_pointer + 0)); // this prints 5
        printf("my age: %d\n", *(int*) (my_hacky_pointer + 1)); // this prints 6
        printf("my age: %d\n", *(int*) (my_hacky_pointer + 2)); // this prints 99
        printf("my age: %d\n", *(int*) (my_hacky_pointer + 3)); // this prints 66
        printf("my age: %d\n", *(int*) (my_hacky_pointer + 4)); // this prints 78
}

我建议不要在任何地方使用它,有更好的方法可以获得同样的结果,这些方法在CPU上更干净、更容易,但我想有人会发现使用指针算法可以实现的结果很有趣.

C++相关问答推荐

当包含头文件时,gcc会发出隐式函数声明警告

C strlen on char array

标准的C17标准是用括号将参数包装在函数声明中吗

在函数中使用复合文字来初始化C语言中的变量

变量>;-1如何在C中准确求值?

为什么可以在typedef之前使用typedef d struct 体?

如何跨平台处理UTF-16字符串?

在编译时参数化类型定义

为什么sscanf不能正确地从这个字符串格式中提取所有数字?

为什么STM32G474RE上没有启用RCC PLL

二进制计算器与gmp

1处的解析器错误:yacc语法的语法错误

为什么Fread()函数会读取内容,然后光标会跳到随机位置?

获取前2个连续1比特的索引的有效方法

使用%f格式说明符打印整数值

试图创建一个基本的Word克隆,但遇到了障碍

如何使这个While循环在新行上结束

通过对一个大的Malloc内存进行切片来使用Malloc的内存片

在Ubuntu上使用库部署C程序的最佳实践

运行以下 C 程序时出现分段错误