Analysis of Declarations in C Language

This article provides a detailed analysis of declarations in the C language, progressing step by step to thoroughly resolve this challenging topic. It is highly recommended to bookmark it.

Pre-Class Question?

What does the following declaration mean?

char *const *(*next)();

First, give your answer. The standard answer will gradually become clear throughout this article’s step-by-step explanation. Let’s see where you went wrong!

  • Why are declarations so important?

Declarations determine the basic type of a variable and its initial value (if any).

0. Declarations and Definitions

Before fully understanding declarations, it is essential to clarify the relationship between definitions and declarations:

Declaration: A statement that can appear multiple times describing the type of an object, used to refer to objects defined elsewhere (for example, in other files), e.g., extern int my_array;

Definition: A statement that can only appear in one place, which determines the type of the object and allocates memory for it, used to create new objects. For example: int myarray[100];

Just remember the following to distinguish between definitions and declarations:

Declaration is equivalent to a regular declaration It does not describe itself, but rather describes objects created elsewhere
Definition is equivalent to a special declaration It allocates memory for the object.

1. Declarators

Declarators are the core of all declarations.

In simple terms, a declarator is an <span>identifier</span> along with any <span>pointers</span>, <span>function parentheses</span>, <span>array subscripts</span>, etc. that are combined with it.

Names and Counts in C Language Forms Appearing in C Language
Pointer (>=0) One of the following forms:* const volatile * volatile * * const* volatile const
Direct Declarator (=1) Identifier or: Identifier[subscript] or: Identifier(parameter) or: (declarator)
Initialization Content (0/1) = initial value

2. Components of a Declaration

A declaration consists of the <span>various parts</span> shown in the table below (not all combinations are <span>valid</span>, but this table describes the vocabulary we will use for further discussion).

Analysis of Declarations in C Language
Components of a declaration, but not all combinations are valid
  • Let’s try a simple example

Let’s see how complex it can get if you use these components to construct a declaration. Remember, there are constraints in valid declarations. You cannot do the following:

Common Mistakes in Declarations (Invalid Declarations)
1. A function cannot return a function, so something like foo()() is invalid.
2. A function cannot return an array, so something like foo is invalid.
3. An array cannot contain functions, so something like foo is invalid.

However, you can replace it with the following:

Correct Replacements for the Above Invalid Declarations
1. A function can return a function pointer, such as: int(* fun())();
2. A function can return a pointer to an array, such as: int(* foo())[]
3. An array can contain function pointers, such as int (*foo[])()
4. An array can contain other arrays, so you often see int foo[][]

3. Priority Rules

So far, we have reviewed the <span>various components</span> of a declaration. This section describes a method to break down declarations using plain language to explain each component.

To understand a declaration, you must grasp the priority rules. Language lawyers love this format; it is highly concise but unfortunately not very intuitive.

There are three rules: A, B, and C.

A: Read the declaration starting from its name, then read according to the priority order.

B: The priority is as follows:

||V
B.1. The part of the declaration enclosed in parentheses

||V
B.2. Suffix operators1. () indicates a function2. [] indicates an array

||V
B.3. Prefix operators
Star <span>*</span>: indicates “pointer to…”

C:<span>const</span>/<span>volatile</span> keyword effect rules.

  • If <span>const</span> and/or <span>volatile</span> are immediately followed by a type specifier (like <span>int</span>, <span>long</span>, etc.), then it applies to the type specifier;

  • In other cases, <span>const</span> and/or <span>volatile</span> apply to the pointer star immediately to their left.

4. Practical Declaration Analysis

We will analyze the C language declaration example at the beginning using the priority rules:

char * const* (*next)();  
Applicable Rules Explanation
A First, look at the variable name “next” and note that it is enclosed in parentheses.
B.1 So first treat the part in parentheses as a whole, concluding that “next is a pointer to…”
B Then consider the things outside the parentheses, making a choice between the prefix star and the suffix parentheses.
B.2 Rule B.2 tells us that the higher priority is the right function parentheses, thus concluding that “next is a function pointer that points to a function returning…”
B.3 Then, handle the prefix “*”, leading to the conclusion about what the pointer points to.
C Finally, interpret “char* const” as constant pointer to a character.

In summary, we conclude:

  • next is a function pointer that points to a function returning a constant pointer to a character.

Specifically, it can be broken down as follows:(char * const)* (*next)()

5. Try Again

Provide the meaning of the declaration:

char*(*c[10])(int **p);

Step-by-step analysis:

Principles Used Explanation
A Find the variable name c, noting that it is enclosed in parentheses. (There are multiple variable names; determine the subject from left to right, clearly here it is c)
B.1 First, treat the enclosed part as a whole, clearly c has prefixes and suffixes.
B.2 Clearly, according to B.2, the suffix has a higher priority than the prefix, so first explain the suffix [], indicating that C is an array, then explain the prefix *, indicating that the type of the array is a pointer, thus C is an array of pointers. At this point, we have successfully explained (*c[10])
B.2 After explaining the parentheses as a whole, let’s look at its prefixes and suffixes; the suffix has a higher priority than the prefix, so first explain (int **p). Clearly, this is a list of functions, with parameters being a two-dimensional pointer, ultimately returning an int type. At this point, it is clear that the latest explanation is:C is an array of pointers, where the array stores function pointers, and the function’s parameter list is int**p
B.3 Looking at the prefix of the parentheses, it is char, clearly indicating that the function’s return value is char, thus the final explanation is:C is an array of pointers, where the array stores function pointers, the parameter list is int**p, and the return type is a character pointer.

So, did your initial answer match the standard answer? Keep it up!

6. Declaration of signal

This is one of the most complex system declarations in C language. As follows:

void (*signal(int sig, void(*func)(int)))(int); 

Now, please explain it and try to simplify it using typedef.

① Explanation:

Using the above ABC three principles for analysis:

Principles Used Explanation
A Find the variable name signal
B.2 Clearly, signal has both prefix and suffix. According to B.2, the suffix has a higher priority than the prefix, so first explain the suffix signal(int sig, void(*func)(int)), indicating that this is a function, with parameters being an int type sig and a function pointer (that returns void, with parameters being int).
B.2 Next, looking at the prefix, it is a pointer, indicating that signal returns a pointer, and the specifics of that pointer need further analysis:
B.2 After explaining the parentheses as a whole, treat it as a whole again, and since the suffix has a higher priority than the prefix, explain (int), which is again a function parameter list, for int type; the prefix is a return type void. Thus, the pointer returned by signal points to a function that returns void and has a parameter list of int.

Therefore, the final explanation is:

signal is a function whose parameter list is: int, a function pointer that accepts an int parameter and returns void; its return type is: a pointer to a function with an int parameter list and a return type of void.

② Typedef Simplification:

Definition: typedef creates an alias for an existing data type

It can be keenly observed that the above declaration is complex due to the <span>function pointer</span><span>,</span><p><figure><span><img alt="Analysis of Declarations in C Language" src="https://boardor.com/wp-content/uploads/2025/10/220e2e59-f295-421c-b923-97d4095875cb.png"/></span><figcaption><span>signal is a function whose parameter list is: int, a function pointer that accepts an int parameter and returns void; its return type is: a pointer to a function with an int parameter list and a return type of void.</span><span> The signal function declaration is greatly complicated by the function pointer.</span></figcaption></figure><p><span>Thus, we can use typedef to define a type alias to simplify the declaration:</span></p><p><span>Define an equivalent function declaration so that </span><code><span>FuncType</span> represents a <span>function pointer</span> with a parameter list of int and a return type of void.

typedef void (*FuncType)(int);

Then the above function declaration can be equivalently expressed as:

Analysis of Declarations in C Language
Original declaration of the signal function||V
typedef void (*FuncType)(int);
FuncType signal(int,FuncType);

With this view, after using typedef, the <span>readability of the function</span> is greatly improved! This is the power of <span>typedef defining aliases</span>!

7. Notes on typedef

Regarding the use of typedef, the previous point has already been made very clear!

The essence is worth reiterating:

typedef creates an alias for an existing data type.

Note 1:

typedef does not create a new data type and can perform typedef declarations on <span>any type</span>.

Note 2:

Multiple type aliases can be defined simultaneously using typedef:

Analysis of Declarations in C Language
Declared:1. Alias for integer pointer type2. Alias for function pointer (parameter list empty, return type int)3. Alias for integer array

Note 3:

typedef must be placed at the beginning of the type declaration.

8. Differences Between typedef and define

Difference 1: Type Expansion

define can expand, but typedef cannot, as follows:

#define peach int;
unsigned peach i;/* no problem */

define can expand type names, the above code is fine.

typedef int banana;
unsigned banana i;/* error! illegal */  

typedef cannot expand type names, the above code will report an error!

Difference 2: Continuity of Declarations

typedef can declare multiple consecutive variables, but define cannot

As follows:

Correct Declaration:

typedef int a,b,c;
All of abc are int type variables, which is allowed!

Incorrect Declaration:

#define int* INT
INT a,b;
Here it merely becomes int *a, b, and will not be transformed into the expected declaration `int* a, *b`, which makes the original pointer type become an integer now, which is not as expected. This is the misuse of define.

Conclusion

Alright, in this section, we discussed the basic knowledge of analyzing declarations in C language. Let’s review:

Review of Knowledge on Declarations in C Language
1. What is a declaration?
2. What is a definition?
3. What is the best way to understand declarations and definitions?
4. What are the components of a declaration?
5. What are the three priority rules for declarations?
6. Provide the meaning of the declaration (char * const)* (*next)();
7. Provide the meaning of the declaration char*(*c[10])(int **p);
8. Provide the meaning of the declaration void (*signal(int sig, void(*func)(int)))(int);
9. Use typedef to simplify the declaration in item 8.
10. What does typedef mean?
11. What are the notes on typedef?
12. What are the differences between typedef and define?
13. What is the type expansion property of define?
14. What is the continuity of typedef declarations?

If you cannot explain each item in this table, then review the above content thoroughly!

Answers can be found in the comments section, and everyone is welcome to discuss~

Analysis of Declarations in C Language

Assembly Language

😉【Assembly Language】1—Basic Hardware Knowledge😉【Assembly Language】2—Basic Knowledge of Registers😉【Assembly Language】3—Interaction Between Registers and Memory😉【Assembly Language】4—The First Complete Assembly Program😉【DOSBox】1-Debug😉【DOSBox】2-Debug Executable Files😉【DOSBox】3—Complete Development Process

C Language

😉【C Language】C Token (C89 C99 C11)😉【C Language】Basics of Pointers😉【C Language】Basics of Arrays😉【C Language】Struct Alignment😉【C Language】Huawei C Language Advanced Test😉【C Language】Summary of Methods to Trigger Refresh to Disk😉【C Traps and Pitfalls】-1-Lexical Traps😉【C Traps and Pitfalls】-2-Syntax Traps😉【C Traps and Pitfalls】-3-Semantic Traps

Linux

😉【Linux】Essential Knowledge Before Learning Linux😉【Linux】Linux Kernel Memory Abstraction for Processes😉【Linux】Overview of Linux 1—Usage of Physical Memory😉【Linux】The Entire Process from Writing Software to Running It😉【Linux】Three Addressing Modes of CPU: Real Mode, Protected Mode, Long Mode😉【Linux】Addressing in Real Mode and Protected Mode, this time explained clearly!😉【Linux】Source Code Directory Structure of Linux 0.11😉【Linux】Makefile Mechanism and Basic Explanation😉【Linux】Compiling and Running Linux 0.11😉【Linux】“Entering the Intranet”—Overview of Linux Kernel Structure😉【Linux】Linux Interrupt Mechanism😉【Linux】Description of Linux Processes😉【Linux 102】1-Makefile😉【Linux 102】2-Makefile.header😉【Linux 102】3-system.map😉【Linux 102】4-bootsect.s😉【Linux 102】5-setup.s😉【Linux 102】6-head.s😉【Linux 102-D】/boot😉【Linux 102】7-main.c

Cloud

😉【Docker】1—Basic Knowledge😉【Cloud Computing】0—The Past and Present of Cloud Computing😉【Cloud Computing】1—Basic Knowledge😉【Cloud Computing】2—Basic Technologies (Computing, Communication, Storage)😉【Cloud Computing】3—Comprehensive Introduction to Huawei Cloud😉【Cloud Computing】4—Usage of Huawei Cloud😉【Huawei Cloud】-1 Elastic Cloud Server-ECS😉【Huawei Cloud】Bare Metal Server (BMS)😉【Huawei Cloud】Image Service (IMS)😉【Huawei Cloud】Elastic Scaling Service (AS)😉【Huawei Cloud】Cloud Container Engine (CCE)

About Xiao Xi

😉 Hehe, I am Xiao Xi, focusing on <span>C Language</span>, <span>Linux Kernel</span>, and <span>Cloud Computing</span>.

Here is my WeChat, looking forward to learning and communicating with you!

Analysis of Declarations in C Language

C_Linux_Cloud

Please note when adding WeChat

Xiao Xi’s motto:<span>Don't underestimate simplicity; simplicity is also difficult. Don't underestimate difficulty; difficulty is also simple.</span>. My articles are all about explaining simple knowledge. If you like this style:

Feel free to follow, comment, and share to let more friends see it~~~🙈

What do you want to see in the next issue? Leave a message in the comments section! See you next time!

Leave a Comment