【问题标题】:Is this valid typecasting use with array of structs?这种有效的类型转换是否与结构数组一起使用?
【发布时间】:2021-01-08 04:06:35
【问题描述】:

在过去,我一直在努力理解指针运算、类型转换和结构数组,有时即使程序可以运行,它在技术上仍然是不正确的,所以我只想运行我写的这段代码并确保我正确理解所有概念。

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

typedef struct
{
  int id, jobType;
  float salary;
} Employee;

Employee * readFileInfo(FILE *fp)
{
  int numEmployees = 0;
  fscanf(fp, "%d", &numEmployees); //find the int at the start of the file to indicate how many employees there are
  int *array = malloc( (sizeof(int)) + ( sizeof(Employee) * numEmployees ) ); //allocate an extra spot for an integer
  *array = numEmployees; //hide the number of employees one integer behind the start of the array, increment on next line
  array++;
  Employee *test = (Employee *) array;
  for(int i = 0; i < 3; i++)
    fscanf(fp, "%d %d %f", &test[i].id, &test[i].jobType, &test[i].salary); //loop through and assign each value to its proper variable
  return test;
}

Employee * getEmployeeByID(Employee *arr, int ID)
{
  for(int i = 0; i < *((int*)arr - 1); i++)
    if(arr[i].id == ID)
        return ((arr) + i); //returns address of specified employee
   return 0;
}

void setID(Employee *p, int ID)
{
  p->id = ID;
  printf("\nset successfuly\n");
}

int getSize(Employee *arr)
{
  return *((int*)arr - 1); //returns the int value hidden before start of array
}

 void getAvgSalary(Employee *arr) //calculates average salary, prints out all employees who make more than that
 {
   float total = 0, avg = 0;
   for(int i = 0; i < getSize((Employee*)arr); i++)
     total += arr[i].salary;

   avg = total / (float)getSize((Employee*)arr);

   for(int i = 0; i < getSize((Employee*)arr); i++)
    if(arr[i].salary >= avg)
        printf("ID: %d has above the avg salary with a salary of $%.2f\n", arr[i].id, arr[i].salary);
 }

 int main(void)
 {
   FILE *fp = fopen("test.txt", "r+");
   Employee *array = readFileInfo(fp);
   Employee *emp2 = getEmployeeByID(array, 2);
   setID(emp2, 5);
   getAvgSalary(array);
 }

test.txt
3 1 5 20000 2 1 100000 3 3 50000

基本上,该程序应该打开 test.txt,调用 readFileInfo 找到文件中的第一个整数(表示要跟随的员工数量),使用 3 个东西为结构数组分配内存:大小号乘以员工结构的大小,并在数组开始之前添加一个额外的整数以“隐藏”该大小变量。之后,在数组上调用各种函数来试验类型转换/指针算法

任何帮助、更正、建议、观察或回应都会很棒!

【问题讨论】:

  • 亲爱的 OP,工作但可能会改进或审查的代码更有可能更适合 C.R.S.E ,因为 S.E.网站恰好为此而存在。
  • @APJo 对不起!不知道那是一回事,我现在就在那里发帖。谢谢!
  • 这打破了严格的别名。对于您想要的,我建议使用一个新结构来保存数组长度(使用更合适的 size_t 类型)和 flexible array member 用于 Employee 数组。
  • 亲爱的 OP,完全没问题 :)

标签: arrays c pointers struct casting


【解决方案1】:

代码不正确。假设float 改为double,则整个结构将具有double 的对齐要求,在x86-64 上为8 个字节。但是您已经强制它对齐 4。它具有未定义的行为,这意味着它可以工作,或者它可以fail catastrophically

幸运的是,这种 hack 的需求为零。只需使用带有灵活数组成员struct

typedef struct
{
  int id, jobType;
  float salary;
} Employee;

typedef struct {
  size_t numEmployees; // use size_t for array sizes and indices
  Employee employees[];
} EmployeeArray;

// allocate sizeof (EmployeeArray) space for the struct
// and sizeof (Employee) space for each array element
EmployeeArray *array = malloc(sizeof *array + sizeof (Employee) * numEmployees);
array->numEmployees = numEmployees;
array->employees[0] = ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多