Can a Function be a Structure Member in C?

Can a Function be a Structure Member in C?

Background

Raw Question

1
2
3
4
5
6
Which of the following cannot be a structure member?

A. Array
B. Another structure
C. Function
D. None of the mentioned

Raw Question

My First Idea

I thought the answer was D, because if the array is stored in the structure as a pointer, then reciprocally, the function pointer could reasonably be a member of the structure (in natural language and common sense). For those who don’t know about function pointers, here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <string.h>

struct person {
char name[5];

void (*fun)(int);
};

void fun(int a) {
printf("Value of a is %d\n", a);
}

int main() {
struct person p1;

// array
strcpy(p1.name, "John");
printf("Name is %s\n", p1.name);

// function
p1.fun = &fun;
p1.fun(10);

return 0;
}

Argument for Function

Someone argue that we can’t define a function in a structure. i.e.

1
2
3
struct person {
char name[20];
};

is legal, and

1
2
3
struct person {
void func() {}
}

is not legal.

I don’t think this idea is valid because reciprocally, the definition of an array should look like this: char name[20] = {'a', 'b', 'c', 'd', 'e'};, because on the function we also define the contents, or codes of the function.

Another Justification

To justify my point, there is another argument.

When using a function pointer, there are two ways, (*p1.fun)(10); and p1.fun(10);, because the function name is a pointer, so they can be used interchangeably. Due to historical reasons, Bell Labs uses the first form 1, while Berkeley uses the second form. For compatibility with existing codes, ANSI C considers these two forms equivalent. Subsequent standards standards also continue this contradictory harmony.

The name of an array is the address of the first element of the array, although they can be used interchangeably because there will be an implicitly conversion:

1
2
3
4
char name[20];
char *p = name;
printf("%c %c\n", *p, name[0]);
printf("%c %c\n", *(p+1), name[1]);

Back to the Standard

To answer this question, we need back to the C standar: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf

Concepts

6.2.1.1 identifier

An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter.

6.2.5.1 object types and function types

Types are partitioned into object types (types that describe objects) and function types (types that describe functions). At various points within a translation unit an object type may be incomplete (lacking sufficient information to determine the size of objects of that type) or complete (having sufficient information).

6.2.5.20 derived types, array, structure, function, pointer

Any number of derived types can be constructed from the object and function types, as follows:

  • An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. The element type shall be complete whenever the array type is specified. Array types are characterized by their element type and by the number of elements in the array. An array type is said to be derived from its element type, and if its element type is T, the array type is sometimes called ‘‘array of T’’. The construction of an array type from an element type is called ‘‘array type derivation’’.
  • A structure type describes a sequentially allocated nonempty set of member objects (and, in certain circumstances, an incomplete array), each of which has an optionally specified name and possibly distinct type.
  • A function type describes a function with specified return type. A function type is characterized by its return type and the number and types of its parameters. A function type is said to be derived from its return type, and if its return type is T, the function type is sometimes called ‘‘function returning T’’. The construction of a function type from a return type is called ‘‘function type derivation’’.
  • A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. A pointer type is a complete object type.

6.7.2.1 structure specifiers

3 A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.

9 A member of a structure or union may have any complete object type other than a variably modified type. In addition, a member may be declared to consist of a specified number of bits (including a sign bit, if any). Such a member is called a bit-field; its width is preceded by a colon.

Summary

  • In C, there are two general types, object type and function type.
  • An object type may be incomplete (lacking sufficient information to determine the size of objects of that type) or complete (having sufficient information).
  • array is drived from its element type, structure is drived from member objects, function is drived from its return type, and pointer is drived from a function type or an object type.
  • A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself).
  • A structure can contain a incomplete member, when that the last member of a structure with more than one named member may have incomplete array type;
  • A structure with last member is incomplete array type shall not be a member of a structure or an element of an array.

Discussion and Conclusion

Therefore, function type cannot be a structure member strictly according to the standard. The correct answer should be C.

However, the explanation of “cannot define a function in structure” leads to the correct answer, but the process is wrong. My idea is also wrong because the idea of pointers is not crucial to the question, the type should be the key point.

In addition, the first two options are flimsy:

  • Array cannot always be a structure member. Array implies complete array (char name[50];) and incomplete array (char name[];), and the incomplete array is only allowed in the last member of a structure with more than one named member. Saying an array can be a structure member is not accurate.
  • Another structure cannot always be a structure member. When another structure contains the last incomplete array member, it cannot be a member of a structure. That option is also inaccurate.

Can a Function be a Structure Member in C?
https://blog.zhanganzhi.com/en/2024/02/2db431afb19a/
Author
Andy Zhang
Posted on
February 16, 2024
Licensed under