简体   繁体   English

这种有效的类型转换与结构数组一起使用吗?

[英]Is this valid typecasting use with array of structs?

In the past I've struggled with understanding pointer arithmetic, typecasting and array of structs, and sometimes even if the program works, it's still technically incorrect, so I just wanted to run this bit of code that I wrote by you guys and make sure I'm understanding all the concepts right right.在过去,我一直在努力理解指针算法、类型转换和结构数组,有时即使程序可以运行,它在技术上仍然是不正确的,所以我只想运行你们编写的这段代码并确保我正确理解所有概念。

#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

Basically, the program is supposed to open test.txt, calls readFileInfo which finds the first integer in the file (which signifies the number of employees to follow), allocates memory for an array of structs using 3 things: that size number multiplied by the size of the employee struct, with one extra integer added to "hide" that size variable before the start of the array.基本上,该程序应该打开 test.txt,调用 readFileInfo,它在文件中找到第一个 integer(表示要跟随的员工数量),使用 3 个东西为结构数组分配 memory:大小乘以employee 结构的大小,添加一个额外的 integer 以在数组开始之前“隐藏”该大小变量。 After that, various functions are called on the array to experiment around with typecasting / pointer arithmetic之后,在数组上调用各种函数来试验类型转换/指针算法

Any help, corrections, advice, observations, or responses at all would be great!任何帮助、更正、建议、观察或回应都会很棒!

The code is not correct.代码不正确。 Assume the float was instead a double , the entire struct would then have the alignment requirement that of a double , which would be 8 bytes on x86-64.假设floatdouble ,那么整个结构将具有 alignment 对double的要求,这在 x86-64 上是 8 个字节。 But you've forced it to alignment 4. It has undefined behaviour which means that it can work, or it can fail catastrophically .但是您已将其强制为 alignment 4. 它具有未定义的行为,这意味着它可以工作,或者它可能会灾难性地失败。

Fortunately there is zero need for this hack though.幸运的是,这个 hack 的需求为零。 Just use a struct with a flexible array member instead:只需使用具有灵活数组成员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] = ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM