-6

I'm studying coding for some credits in the university, and I was studying and decided to try to make something with structs in C++ to try to understand them better.

I'm trying to make some functions to work with the struct, but they only work if I write & before declaring the arguments, but in the classroom we were told it should not be necessary. My code is the following.

struct employee{
   int ID;
   char name;
   double salary;
};

struct empresa{
   char name;
   struct employee employee[];
};


void iterate_trough_employees(struct empresa &empresa, int number_employees){
    for ( int i = 0; i < number_employees; i++){
       empresa.employee[i].ID = i+1;
       printf("\n\n EL ID del empleado es:\t %d \n",empresa.employee[i].ID);
       empresa.employee[i].salary = rand() % 50;
       printf("El salario del empleado es: %.1lf \n", empresa.employee[i].salary);
       }
}

void sort_this(struct empresa &empresa, int number_employees){
   int list_of_ID[number_employees];
   list_of_ID[0]= empresa.employee[4].ID;
   printf("\n%d", empresa.employee[4].ID);
   printf("\n%d", list_of_ID[0]);
   printf("\n%.0lf\n", empresa.employee[6].salary);
}

int main(){
   struct empresa empresa;

   int empleados = 10;
   int orden_salarios[10];
   iterate_trough_employees(empresa, empleados);
   printf("%d", empresa.employee[6].ID);
   sort_this(empresa, empleados);

   return 0;
}

I'm mostly interested in the sort_this function, which only shows the correct values on screen when I write the K (the code in the function is not related to the title, because I have been trying to figure out the mistake making an easier function).

For those asking, we've been taught to code in C using some C++ elements (such as the pass by reference from C++ or cin/cout) to make it easier, and therefore it may seem to you that the code is not C nor C++. I'm studying coding for some credits in the university, and I was studying and decided to try to make something with structs in C++ to try to understand them better.

I'm trying to make some functions to work with the struct, but they only work if I write & before declaring the arguments, but in the classroom we were told it should not be necessary. My code is the following.

struct employee{
   int ID;
   char name;
   double salary;
};

struct empresa{
   char name;
   struct employee employee[];
};


void iterate_trough_employees(struct empresa &empresa, int number_employees){
    for ( int i = 0; i < number_employees; i++){
       empresa.employee[i].ID = i+1;
       printf("\n\n EL ID del empleado es:\t %d \n",empresa.employee[i].ID);
       empresa.employee[i].salary = rand() % 50;
       printf("El salario del empleado es: %.1lf \n", empresa.employee[i].salary);
       }
}

void sort_this(struct empresa &empresa, int number_employees){
   int list_of_ID[number_employees];
   list_of_ID[0]= empresa.employee[4].ID;
   printf("\n%d", empresa.employee[4].ID);
   printf("\n%d", list_of_ID[0]);
   printf("\n%.0lf\n", empresa.employee[6].salary);
}

int main(){
   struct empresa empresa;

   int empleados = 10;
   int orden_salarios[10];
   iterate_trough_employees(empresa, empleados);
   printf("%d", empresa.employee[6].ID);
   sort_this(empresa, empleados);

   return 0;
}

I'm mostly interested in the sort_this function, which only shows the correct values on screen when I write the K (the code in the function is not related to the title, because I have been trying to figure out the mistake making an easier function).

For those asking, we've been taught to code in C using some C++ elements (such as the pass by reference from C++ or cin/cout) to make it easier, and therefore it may seem to you that the code is not C nor C++.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • This is C++, not C. – Oliver Charlesworth Dec 15 '17 at 11:49
  • 12
    You pass arguments by reference which doesn't exist in C, and you use a [flexible array member](https://en.wikipedia.org/wiki/Flexible_array_member) and [variable-length arrays](https://en.wikipedia.org/wiki/Variable-length_array) which doesn't exist in C++. So this code is not valid in either language. – Some programmer dude Dec 15 '17 at 11:50
  • 2
    If you don't even know which programming language you are using, there isn't much hope to produce any form of working software... – Lundin Dec 15 '17 at 11:50
  • 1
    Is this valid in C++: `struct empresa empresa;` ? Looks like neither C++, nor C for me. – Gerhardh Dec 15 '17 at 11:52
  • 1
    Can you explain the effect of "write & before declaring the arguments" ? Does your problem exist for struct parameters you are only reading ? Or only for those which you try to change inside the function? – Yunnosch Dec 15 '17 at 11:52
  • 3
    As for your problem, perhaps you should [get a good C++ beginners book or two](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) and start over. – Some programmer dude Dec 15 '17 at 11:53
  • You do not need to provide the `struct` keyword before using a `struct`'s name as a type. `struct` are implicitly type names in c++. This is a relic from c. – François Andrieux Dec 15 '17 at 11:57
  • @Gerhardh: That's valid in both. `struct empresa` names a type, `empresa` names a variable. – Oliver Charlesworth Dec 15 '17 at 11:57
  • @Gerhardh Yes, it's valid. It's inherited from c and kept in the language for compatibility. It specifies that the following identifier is a struct type. – François Andrieux Dec 15 '17 at 11:58
  • @Gerhardh It's valid in both C and C++, however you'll immediately run into problems in C++ if you do so. See [this answer](https://stackoverflow.com/a/47347568/5958455) of mine. – iBug Dec 15 '17 at 12:00
  • 1
    @OliverCharlesworth Doesn't C++ automatically define a type with same name when defining a struct? I know that it is valid in C. – Gerhardh Dec 15 '17 at 12:00
  • 11
    FWIW, "*we've been taught to code in c using some c++ elements*" - tell your teacher that this is a terrible way to learn, as you'll end up learning neither language properly. Indeed, the symptoms you're seeing relate to the `&`, which is a C++ feature. – Oliver Charlesworth Dec 15 '17 at 12:00
  • 1
    @Gerhardh - It's retained in C++ as a vestigial back-compatibility thing. – Oliver Charlesworth Dec 15 '17 at 12:01
  • 2
    Given that the declaration is `struct empresa empresa` and no custom allocation, `empresa` does not contain space for even a single employee. Everything beyond that is accessing unallocated memory. – dhke Dec 15 '17 at 12:02
  • What is **certain** is that this code **isn't** C or any extension, because of the `&` pass-by-reference. – Antti Haapala -- Слава Україні Dec 15 '17 at 12:56
  • 1
    _"[I] decided to try to make something with structs in C++ to try to understand them better."_ Why didn't you first try to understand the basic syntax of the language, like pointers, references, values, and the difference between them, particularly regarding functions? There's no point in coding custom structs and functions if you don't get grok the fundamentals of the language. It doesn't make for a useful question, anyway, as it demonstrates a lack of basic research before posting. You shouldn't learn programming by trial and error, and we shouldn't help you to do so. – underscore_d Dec 15 '17 at 13:07

1 Answers1

3

When you declare a function with void foo(struct bar x) and you call it with foo(y), the compiler makes a copy of y and assigns that copy to x. Then changing the copy x inside the function has no effect on the original y.

When you declare a function with void foo(struct bar *x) and you call it with foo(&y), the compiler takes the address of y and assigns that value to x. Then x is a copy of the address, but you use *x or x->member inside the function, and these refer to the object at the address. Since the address points to the original object y, changing *x and x->member change the original object y.

When you declare a function with void foo(struct bar &x) and you call it with foo(y), the compiler takes the address of y and passes that to the function. When compiling the function, the compiler knows x is supposed to be a reference, not a pointer to or a copy of the original object. So, wherever x is used in the function, the compiler uses the address it was passed to refer to the original object. So changes to x in the function are changes to the original object. Where you write x.member = something;, the compiler uses the address that was passed for x to change the value of member in the original object y. This feature is only in C++; it is not in C.

The first is called pass by value.

The third is called pass by reference.

The second is equivalent to pass by reference except that it is manual instead of automatic; you explicitly pass a pointer and must manually write out the *x or x->member instead of x or x.member.


A note about struct empresa empresa; in main. Your struct empresa is defined with struct employee employee[];. This is a flexible array member, and defining an object of that type in this way does not allocate any storage for elements of the array. The proper way to use it is allocate storage for the base structure (sizeof(struct empresa)) plus as many elements as you want (+ empleados * sizeof(struct employee)). To do this, you will have to use malloc or a related function.

Flexible array members are an extension supported by some C++ implementations. They are not a standard part of the language.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • 3
    In your third paragraph " the compiler takes the address of y and passes that to the function" is a possible implementation detail. The actual language specification is that `y` is passed to the function by reference – M.M Dec 15 '17 at 12:53
  • @M.M: View it as a description of the abstract model, subject to implementation in any way the compiler chooses. – Eric Postpischil Dec 15 '17 at 14:22