1

To start, none of the existing solutions I have looked through have the parameter as an array, such as:

void inputCars(Car * cars[], int size);

Here is the code I currently have.

/******************************************************************************
WE WANT:
dynamic array of pointers to a
car structure
*******************************************************************************/
#include <string.h>
#include <stdio.h>

typedef struct {
 char make[60];
 double price;
 int year;
}Car;

int size;

void inputCars(Car* cars[], int size);

int main(int argc , char** args)
{
    printf("Enter how many Cars you wish to take inventory of: ");
    scanf("%d", &size); 
    Car cars[size];
    inputCars(&(cars), size);

}

void inputCars(Car * cars[], int size)
{
    for(int i = 0; i < size; i++)
    {
           // TODO
    }
    
}

When I try to put the cars array through I get the following error :

 expected 'struct Car**' but argument is of type 'struct Car(*)[(sizetype)(size)]'

I understand what Car * cars[] is asking, thanks for the help with that, but I am confused on how I can pass this through.

I am not allowed to change the way the parameters are in the function and am utterly confused as to how to pass the array through.

6 Answers 6

3

In this statement

Car cars[size];

there is declared a variable length array.

In this call

inputCars(&(cars), size);

the expression &cars has the type Car( * )[size]. But the corresponding function parameter

void inputCars(Car* cars[], int size);

is declared like Car * cars[] that is adjusted by the compiler to the type Car ** and there is no implicit conversion from one pointer type to another. So the compiler issues an error message.

In the comment to your program there is written

WE WANT:
dynamic array of pointers to a
car structure

So instead of declaring a variable length array you need to allocate dynamically an array of pointers to objects of the type Car. Something like

Car **cars = malloc( size * sizeof( Car * ) );

for ( int i = 0; i < size; i++ )
{
    cars[i] = malloc( sizeof( Car ) );
}

In this case the function can be called like

inputCars( cars, size );
Sign up to request clarification or add additional context in comments.

Comments

1

Because an array passed as parameter decays to a pointer to the first element of that array, what you have here:

void inputCars(Car* cars[], int size);

Is effectively:

void inputCars(Car** cars, int size);

So you need to pass a parameter of type Car** which Car[size] is not. You taking the address of car (&car) makes no difference, the parameters are still incompatible.

4 Comments

I guess he meant why &car is not Car** when he takes address of an array.
@Afshin I guess so, still, the OP asks how they should pass the array through.
Like I get this, it is a pointer to an array which is just a pointer to a pointer of Cars in this case. I am confused on how I can pass this to the function. I have tried using calloc but to no avail. So yes my question is poorly worded. My apologies, will make the changes now. @anastaciu
@James_B a pointer to array and a pointer to pointer are two completely different things, don't confuse them.
1

What you provide as a parameter to the function is a pointer to an array (of length size) of Car structures whilst the function expects a pointer to a pointer to Car:

'expected struct Car**'.

Comments

0

If you want to pass a pointer to a variadic length array of a given length, you need to prototype it as follows:

void inputCars(int size, Car (*cars)[size]);

or as:

void inputCars(int size, Car (*cars)[*]);

with a later definition supplying the dimension ([*]) expression:

void inputCars(int size, Car (*cars)[size]) { /*...*/ }

The [*] expression may be more complex, include e.g., function calls, and it may be entirely private to the definition, that's why it can be omitted via the * notation in the prototype.

In any case, if the dimension expression is to be based on the size parameter, the size parameter needs to come first.

Example program:

#include <string.h>
#include <stdio.h>

typedef struct {
 char make[60];
 double price;
 int year;
}Car;


void inputCars(int size, Car (*cars)[size]);

int main(int argc , char** args)
{
    int size;
    printf("Enter how many Cars you wish to take inventory of: ");
    if(1!=scanf("%d", &size)) return 1;
    Car cars[size];
    inputCars(size, &(cars));

}

void inputCars(int size, Car (*cars)[size])
{
    //prints the same number twice
    printf("size=%d count=%zu\n", size,sizeof(*cars)/sizeof((*cars)[0]));
}

Keep in mind that using unrestricted VLAs like this isn't very advisable. You're opening your program to the risk of stack overflow (the real thing).

Comments

0

If you cant change the prototypes then you need to allocate the array of pointers and then allocate the space for the cars.

void inputCars(Car *cars[], int size) {
    // (*cars) below dereferences the Car** and gives a Car*
    for(int i = 0; i < size; i++) {
        // TODO
        cars[i] -> year = i; // just an example value to fill it with
    }
}

int main() {
    printf("Enter how many Cars you wish to take inventory of: ");
    
    size_t size;
    if(scanf("%zu", &size) != 1 || size < 1) return 1;    

    Car **cars = malloc(size*sizeof(*cars));
    for(size_t n = 0; n < size; n++)
    {
        cars[n] = malloc(sizeof(*cars[0]));
    }
    inputCars(cars, size);                 // 

1 Comment

Glad you liked some parts in my example at least :-) You may want to remove my comment in the inputCars function though. It doesn't apply to your version.
-1
  • &(cars) (or simply &cars) is the address of a variable pointing at a variable length array (VLA) of Car - a Car (*)[size].
  • Simply passing cars would make it decay into a Car*, not a Car*[] (or Car**) as required by the function.

I suspect that you are supposed to allocate the memory dynamically and pass a pointer to the pointer owning that memory.

Example:

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

typedef struct {
    char make[60];
    double price;
    int year;
} Car;

void inputCars(Car *cars[], int size) {
    // (*cars) below dereferences the Car** and gives a Car*
    for(int i = 0; i < size; i++) {
        // TODO
        (*cars)[i].year = i; // just an example value to fill it with
    }
}

int main() {
    printf("Enter how many Cars you wish to take inventory of: ");
    
    int size;
    if(scanf("%d", &size) != 1 || size < 1) return 1;    

    Car* cars = malloc(size * sizeof(Car)); // or sizeof(*cars) - allocate

    inputCars(&cars, size);                 // &cars is now a Car** (or Car*[])
 
    free(cars);                             // release allocated memory
}

Note: This answer stirred up a discussion about whether &cars is a Car** or not. If it wasn't a Car** the program would have undefined behavior (utterly bad) - but I say that &cars is a Car** and that the program has defined behavior until proven otherwise.

However: Even though this is code that works correctly, it may not have been what was expected of you. Look at Vlads answer for an alternative if this doesn't cut it.

13 Comments

I would suggest sizeof(*cars). Better to use objects instead of types in sizeof-s
inputCars(Car *cars[] => inputCars(Car cars[] or inputCars(Car *cars then (*cars)[i].year => cars[i].year. The array pointer is used wrong way
This is it. Worst part was I tried this at the start (hours ago), but I forgot stdlib.h and did not read the error logs properly. Silly mistake. Tanks for your help.
@0___________ I mention the sizeof(*cars) variant as an option in the comments.
@James_B You're welcome by the way :-) I'm glad you choose Vlad's answer in the end. Even though my answer works, it would probably surprise your teacher. You could get a + for thinking outside the box or a - for not understanding the task as he/she saw it when creating that function signature, depending on the teacher's mood.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.