SoFunction
Updated on 2025-03-02

Exploring the priority of pointer and array operators in C++

Operator priority related to pointers and arrays in C++, explains the left-combination and right-combination method of operators through actual code examples, and how to use parentheses () to change the default binding order. The article also provides a priority table, listing the priority and binding of operators, helping readers better understand the order of operators in complex expressions. Especially for the case where left-combination and right-combination operators exist at the same time, detailed analysis and examples are given, allowing readers to deeply understand the actual application of operator priority.

Operator priority related to pointers and arrays

The following table shows the priority of related operators, with 4 levels, and operators within the same level are called in sequence according to binding nature. These 4 classes are also the 4th level with the highest priority among all operators, and the other operators have lower priority than them:

Priority Operators describe Bonding
1 :: Scope analysis Left combination
2 ()
[]
.
->
Combining forced operations, function parameter list
Array element subscript access
Member access to the class
Member access to class pointer
Right combination
3 (int)
*
&
Cases
Pointer dereference
Variable address
Left combination
4 .*
->*
Member function pointer of class
Member function pointer of class pointer
Left combination

What is prone to confusion and requires careful priority judgment is oftenOne left combination plus one right combination,For example:

  • *ptr[]
  • (int)a()
  • &obj->data
  • obj->*fun()

Please remember oneImportant Methods: When we need to change the order of the operators' union (the default priority of C++ is not our wish), we can add()The person forced the priority order because()It is a type of operator with the highest priority other than ::.

Simple example: Using [] and * as examples to explore the rules of operator combination

The following p1 and p2 are arrays and p3 are pointers:

int *p1[2];    // p1 is an array with 2 elements and each element is (int*)int *(p2[2]);  // Equivalent to *p2[2], p2 is an arrayint (*p3)[2];  // p3 is a pointer pointing to an int array, and the number of elements in this int array must be 2!

So just remember two points:

  • [] has a higher priority than *: i.e.*p1[2]and*(p1[2])equivalence.
  • This priority applies toDefinition statement (* is a pointer definition character)andExecute statement (* is a dereference character)middle:
int *p1[2];    // Definition statement: First look at []:p1 is an array, the number of elements is 2, and each element is (int*).  Equivalent to *(p1[2])int (*p2)[2];  // Definition statement: First look at *: p2 is a pointer pointing to an int array. The number of elements in this int array must be 2!cout << "*p1[0] = " << *p1[0] << endl;     // Execution statement: First look at []: take the 0th element first, and then dereference it.  Equivalent to *(p1[0])cout << "(*p2)[0] = " << (*p2)[0] << endl; // Execution statement: first look at *: dereference first, then take the 0th element

Complete example:

#include <iostream>
using namespace std;

int main(){	
	// The priority of [] is higher than *, so the following p1 is an array and p2 is a pointer:	int *p1[2];    // p1 is an array with 2 elements and each element is (int*).  Equivalent to *(p1[2])	int (*p2)[2];  // p2 is a pointer pointing to an int array, and the number of elements in this int array must be 2!	int a = 1, b = 2;
	int c[2] = {4,5};
	p1[0] = &a;
	p1[1] = &b;
	p2 = &c;
	cout << "*p1[0] = " << *p1[0] << endl;
	cout << "*p1[1] = " << *p1[1] << endl;
	cout << "*(p1[0]) = " << *(p1[0]) << endl;  // Equivalent to the above two	cout << "*(p1[1]) = " << *(p1[1]) << endl;
	cout << "(*p2)[0] = " << (*p2)[0] << endl;  
	cout << "(*p2)[1] = " << (*p2)[1] << endl;
	
	return 0;
}

Output:

*p1[0] = 1
*p1[1] = 2
*(p1[0]) = 1
*(p1[1]) = 2
(*p2)[0] = 4
(*p2)[1] = 5

Complex Example: Exploring how to define priority when left-bound and right-bound operators exist at the same time

The following examples are quite complicated and require patient and careful reading and experience. If this example can be clarified, then I believe your understanding of operator priority will rise to a higher level.

This example examines the binding order when the left and right binding operators exist at the same time, and also demonstrates that it can be used()Force artificially specify the binding order:

#include <iostream>
#include <string>
using namespace std;

class Student{
public:
	Student(string name, int id):_name(name),_id(id){}
	void printInfo(){
		cout << "I am a student. My name is " << _name << ". My id is " << _id << endl;
	}
	void operator()(){
		printInfo();
	}
protected:
	string _name;
	int _id;
};

class Student2 : public Student{
public:
	Student2(string name, int id):Student(name, id){}
	void printInfo(){
		cout << "I am a super Student!!! " << endl;
	}
	void operator()(){
		cout << "I am Student2!!!" << endl;
	}
};

struct StudentWrapper{
	Student* _ps;
	StudentWrapper(Student* ps):_ps(ps){}
	Student* operator()(){return _ps;}
};

int main(){	
	// . and (), -> and () level: from left to right	cout << "-----------------1------------------" << endl;
	Student s1("Bob",101), s2("Jack", 102);
	Student *ps1 = new Student("Eric",103);
	();
	();
	ps1->printInfo();

	// .Above *: Combine first.	cout << "-----------------2------------------" << endl;
	// The following statement reports an error: call .printInfo() first, then *, so an error will be reported	// *();  // error: request for member 'printInfo' in 'ps1'
	(*ps1).printInfo(); 
			
	// . and () are higher than *: first combine () and . (from right to left), and finally combine *	cout << "-----------------3------------------" << endl;
	StudentWrapper sw(ps1);
	// The following statement reports an error: first combine sw(), then combine.printInfo(), and finally combine *, so an error will be reported	// *sw().printInfo(); // error: request for member 'printInfo' in '::operator()()'
	(*sw()).printInfo(); // correct: sw() first, then *sw(), then (*sw()).printInfo()	// The following statement reports an error: first combine sw(), then (), and finally *, so an error will be reported	// *sw()(); // error: expression cannot be used as a function
	(*sw())(); // correct: sw() first, then *sw(), then (*sw())()
	// (int) and ()/[]: first combine () and [], then forcefully turn	cout << "-----------------4------------------" << endl;
	Student2 ss("Alice", 999), sss("Jason", 998), ssArray[2] = {ss, sss};
	ss();   // Call Student2::operator()	// The following statement reports an error because it will first combine ss() and then cast it	// (Student)ss(); // error: invalid use of void expression
	((Student)ss)(); // correct: Call Student::operator()	// The following statement reports an error because it will first combine ssArray[0], then ssArray[0](), and then cast	// (Student)ssArray[0](); // error: invalid use of void expression
	((Student)ssArray[1])(); // correct: After casting ssArray[1] to Student type, call its() method
	// () higher than .* and ->*: first combine ()	cout << "-----------------5------------------" << endl;
	void (Student::*fp)();
	fp = Student::printInfo;
	// s1.*fp();   // error: must use '.*' or '->*' to call pointer-to-member function in 'fp (...)'
	(s1.*fp)();
	(s2.*fp)();
	// ps1->*fp(); // error: must use '.*' or '->*' to call pointer-to-member function in 'fp (...)'
	(ps1->*fp)(); 
	
	// (int) higher than .* and ->*: first combine (int)	cout << "-----------------6------------------" << endl;
	Student2 *ssp = &sss;   // Jason
	void (Student2::*fp2)();
	fp2 = Student2::printInfo;
	(ss.*fp2)();
	((Student)ss.*fp)();  // First force ss to Student, then call Student::printInfo(), note that it is .*fp instead of .*fp2	((Student*)ssp->*fp)();  // First force ssp to Student*, and then call Student::printInfo(), note that it is .*fp instead of .*fp2
	// *Above.* and ->*: Combine* first	cout << "-----------------7------------------" << endl;
	(*ssp.*fp2)();   // *ssp first, then .*fp2	Student2 **sspp = &ssp;
	(*sspp->*fp2)(); // *sspp first, then ->*fp2	
	delete ps1;
	return 0;
}

Output:

-----------------1------------------
I am a student. My name is Bob. My id is 101
I am a student. My name is Jack. My id is 102
I am a student. My name is Eric. My id is 103
-----------------2------------------
I am a student. My name is Eric. My id is 103
-----------------3------------------
I am a student. My name is Eric. My id is 103
I am a student. My name is Eric. My id is 103
-----------------4------------------
I am Student2!!!
I am a student. My name is Alice. My id is 999
I am a student. My name is Jason. My id is 998
-----------------5------------------
I am a student. My name is Bob. My id is 101
I am a student. My name is Jack. My id is 102
I am a student. My name is Eric. My id is 103
-----------------6------------------
I am a super Student!!!
I am a student. My name is Alice. My id is 999
I am a student. My name is Jason. My id is 998
-----------------7------------------
I am a super Student!!!
I am a super Student!!!

This is the article about exploring the priority of pointers and array operators in C++. For more related content on C++ pointers and array operators, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!