I don't really understand what Visual Studio 2019 wants from me (C language). On one hand it doesn't throw me either error or warning, but on the other hand it marks me with a green squiggling the createCustomer
decaration in my API file. I would like to encapsulate Customer and use ADT on Customer structure.
These are my source and header files:
customer.h
#include <stdlib.h>
typedef struct Customer
{
unsigned int customerId;
const char* name;
int numOrders;
}Customer, * CustomerPtr;
customer.c
#include "customer.h"
#define MAX_NO_OF_CUSTOMERS 10
static Customer objectPool[MAX_NO_OF_CUSTOMERS];
static unsigned int customersCount = 0;
CustomerPtr createCustomer(const char* name, size_t numOrders)
{
CustomerPtr newCustomer_p = NULL;
if(customersCount < MAX_NO_OF_CUSTOMERS)
{
newCustomer_p = objectPool (customersCount );
newCustomer_p->name = name;
newCustomer_p->numOrders = numOrders;
}
}
customer_api.h
#include "customer.h"
CustomerPtr createCustomer(const char* name, int numOrders);
main.c
#include <stdio.h>
#include "main.h"
#include "customer_api.h"
int main()
{
CustomerPtr customer_p = createCustomer("Demo", 5);
return 0;
}
So as I said, under customer_api.h
the following CustomerPtr createCustomer(const char* name, int numOrders);
has squiggle under the function declaration createCustomer
. The program compiles and run successfully without errors/warnings.
Maybe I'm not using correctly the API h file concept? I'm trying to keep the customer properties implementation hidden from external files, so in other files I just include customer_api.h
anytime I need to approach the customer module.
CodePudding user response:
On one hand it doesn't throw me either error or warning …
You should enable all warnings in your project settings; see: Why should I always enable compiler warnings? With warnings enabled, your code (or a version of it I pasted into my VS 2019 IDE) generates 5 warnings:
warning C4255: 'main': no function prototype given: converting '()' to '(void)'
warning C4189: 'customer_p': local variable is initialized but not referenced
warning C4028: formal parameter 2 different from declaration
warning C4267: '=': conversion from 'size_t' to 'int', possible loss of data
warning C4716: 'createCustomer': must return a value
Now, #1, #2 and #4 can be put aside (for now); the big issues are #3 and #5.
To address #3: You need to make the arguments in your function definition (in "customer.c") the same as in the prototype (in "customer_api.h"); presumably, as the numOrders
member of your structure is an int
, you should change the former to have an int
second argument (this also addresses and removes warning #4):
To address #5: The createCustomer
function must return what it is declared to return: a CustomerPtr
object. The local variable, newCustomer_p
, is the obvious candidate for this.
Here is a 'fixed' version of that function:
CustomerPtr createCustomer(const char* name, int numOrders)
{
CustomerPtr newCustomer_p = NULL;
if (customersCount < MAX_NO_OF_CUSTOMERS) {
newCustomer_p = objectPool (customersCount );
newCustomer_p->name = name;
newCustomer_p->numOrders = numOrders;
}
return newCustomer_p;
}
This leaves warnings #1 and #2. To fix #1, add void
as the argument list for main
(the empty parentheses don't actually define a function in C). Presumably, you'll be doing something with the unused variable, at some point, so that will address #2.
int main(void) // Note the EXPLICIT void argument list; () just means "unspecified" in C
{
CustomerPtr customer_p = createCustomer("Demo", 5);
// Do something with "customer_p"
(customer_p);
return 0;
}
… but on the other hand it marks me with a green squiggling.
Hovering the mouse over the squiggles will show the problem: "Function definition for 'createCustomer' not found." This is caused by the issue that generates warning #3; fixing that resolves the green squiggles.
CodePudding user response:
To keep the implementation of the type Customer hidden from the client module you need to put the structure definition in the C file. Here is one way to do it. In the code below I call CustomerPtr simply Customer because I think it is cleaner. For the sake of simplicity and consistency it's a good practice to use the same name of the customer implementation and header file as the customer data type. I also recommend using the prefix Customer_
for each function in Customer.h
. I have also made a few other adjustments.
Customer.h
#ifndef CUSTOMER_H
#define CUSTOMER_H
#include <stdlib.h>
typedef struct CustomerDesc *Customer;
Customer Customer_Create(const char *name, size_t numOrders);
#endif
Customer.c
#include "Customer.h"
#define LEN(array) (sizeof (array) / sizeof (array)[0])
struct CustomerDesc {
unsigned int customerId;
const char *name;
int numOrders;
};
static struct CustomerDesc objectPool[10];
static unsigned int customersCount = 0;
Customer Customer_Create(const char *name, size_t numOrders)
{
Customer newCustomer = NULL;
if (customersCount < LEN(objectPool)) {
newCustomer = objectPool customersCount;
newCustomer->name = name;
newCustomer->numOrders = numOrders;
customersCount ;
}
return newCustomer;
}
main.c
#include "Customer.h"
int main(void)
{
Customer customer = Customer_Create("Demo", 5);
return 0;
}