Both approaches work: passing full array or struct object, and passing addresses only. But passing a pointer is less costly and more flexible than passing the object in its entirety.
Passing pointers is:
Less costly because when passing the full array, or struct variable the entire memory content for either is copied to a new location on the stack. And because typically struct
and array variable are created as collections of large amounts related data, the cost benefit can be substantial. The size of data copied will determine how long it takes to copy, and how much memory will be used to accommodate.
Passing a pointer to either data type, no matter how much data the variable is defined to contain, will only cost the size of a pointer. If targeting 32bit addressing, the size of a pointer variable will be 4 bytes. If targeting 64bit addressing, then the cost is 8 bytes.
More flexible because, for these data types in particular, designing your code to pass pointers adds the ability to add struct members, or array elements without impacting the prototype of the functions that accept them as arguments. For example, the following function prototype will accept both of the following struct definitions:
void acceptStructPointer(S *data);
Will accept either struct definition without impact:
typedef struct {
int val[10];
}S;
Or:
typedef struct {
int val[10];
float b[100];
char string[100];
}S;
Additionally, when memory needs are not know until run-time, for example when reading from a data base, or when spawning multiple instances of socket sessions, passing pointers means that memory needs can be sized based on actual run-time needs:
void acceptStructPointer(S *data)
{
...
data = malloc(someDemand*sizeof(S));
if(data)
{
....
The following is a small code snippet showing in particular the size/speed advantage of passing pointers. Note that the larger, and/or more complex the data object, the bigger the advantage becomes in terms of run-time speed and memory usage.
#define ARY_SIZE 10
typedef struct {
int val[10];
}S;
//struct
S sData = {1,2,3,4,5,6,7,8,9,0};
//pointer to struct
S *pSdata = NULL;
//array
int aData[ARY_SIZE] = {9,8,7,6,5,4,3,2,1,0};
//pointer to array
int *pAdata = NULL;
void acceptPointerVaraibles(S *pA, int *pD);
void acceptNonPointerVariables(S a, int d[]);
int main(void)
{
pSdata = &sData;
pAdata = &aData[0];
printf("Size of struct sData: %d\n", sizeof(sData));
printf("Size of struct pSdata: %d\n", sizeof(pSdata));
printf("Size of struct aData: %d\n", sizeof(aData));
printf("Size of struct pAdata: %d\n", sizeof(pAdata));
//passing pointer
acceptPointerVaraibles(pSdata, pAdata);
//passing non pointer
acceptNonPointerVariables(sData, aData);
return 0;
}
void acceptPointerVaraibles(S *pA, int *pD)
{
for(int i=0;i<ARY_SIZE;i++)
{
printf("Value of struct val element %d: %d\n", i, pA->val[i]);
printf("Value of array element %d: %d\n", i, pD[i]);
}
return;
}
void acceptNonPointerVariables(S a, int d[])
{
for(int i=0;i<ARY_SIZE;i++)
{
printf("Value of struct val element %d: %d\n", i, a.val[i]);
printf("Value of array element %d: %d\n", i, d[i]);
}
return;
}