C language -- on operators

Keywords: C Back-end

Subscript references, function calls, and structure members

[] subscript reference operator

Operand: an array name + an index value

#include<stdio.h>
void main()
{
	int arr[10]; //Create array
	arr[9] = 10; //Use subscript reference operators
	//The two operands of [] are arr and 9
}

() function call operator

The function operator () accepts one or more operands: the first operand is the function name, and the remaining operands are the parameters passed to the function

# include<stdio.h>
void test1()
{
	printf("test\n");
}

void test2(const char *str) //const defines that a variable is not allowed to be changed and has a static effect
{ 
	printf("%s\n", str);
}
void main()
{
	test1(); //() as function call operator
	const char *str = "hello,world";
	test2(str);  //() as function call operator
}

Accessing members of a structure

There are two ways:

. structure. Member name
->Structure pointer - > member name

#include<stdio.h>
//Access a structure member
struct Stu
{
	char name[10];
	int age;
	char sex[5];
	double score;
};

void set_age1(struct Stu stu)
{
	stu.age = 18;
}

void set_age2(struct Stu* pStu)
{
	pStu->age = 18; //Structure member access
}
void main()
{
	struct Stu stu;
	struct Stu* pStu = &stu;//Structure member access

	stu.age = 20; //Structure member access
	set_age1(stu);

	pStu->age = 20; //Structure member access
	set_age2(pStu);
}

Expression evaluation

The order of expression evaluation is partly determined by the priority and associativity of operators;
Operands of some expressions may need to be converted to other types during evaluation

Implicit type conversion

The integer arithmetic operation of C is always performed at least with the precision of the default integer type;
In order to achieve this precision, the characters and short integer operands in the expression need to be converted to ordinary integers before use. This conversion is called integer promotion.

Significance of integer lifting:

  1. The integer operation of the expression shall be executed in the corresponding operation device of the CPU. The byte length of the operand of the shaping operator (ALU) in the CPU is generally the int byte length, which is also the general register length of the CPU;
  2. Therefore, even if the two char types are added, they actually have to be converted to the standard length of the integer operand in the CPU when the CPU executes;
  3. It is difficult for a general-purpose CPU to directly add two 8-bit integers, so all integer values whose length may be less than int in the expression need to be converted to int or unsigned int before they can be sent to the CPU for operation.
void main()
{
	char a, b, c;
	b = 33;
	c = 34;
	a = b + c;
	printf("%c,  %d\n", a, a);
	printf("%c,  %d\n", b, b);
	printf("%c,  %d\n", c, c);
}

In the above code, the values of b and c will be promoted to ordinary integers, and then the addition operation will be performed;
After the addition operation is completed, the result will be divided into stages and then stored in a.
Method of integer lifting:

Signed integer lifting, high-order supplementary sign bit;

char c1 = -1;
char type one byte, - 1:
Original code: 1000 0001;
Complement: 1111;
Lifting: 1111 1111 1111 1111 1111 1111 1111 1111 1111

char c2 = 1;
Original code: 0000 0001
Lifting: 0000 0000 0000 0000 0001

Unsigned integer lifting, high complement 0

Code example:

#include<stdio.h>
//Integer lift example 1
void main()
{
	char a = 0xb6;
	//1011 0110
	//1111 1111 1111 1111 1011 0110 -- lifting, complement
	//1111 1111 1111 1111 1011 0101 -- inverse code
	//1000 0000 0100 1010 -- original code
	//-0x4a
	short b = 0xb600;
	//1011 0110 0000 0000
	//1111 1111 1011 0110 0000 0000 -- lifting, complement
	//1111 1111 1011 0101 1111 1111 -- inverse code
	//1000 0000 0100 1010 0000 -- original code
	//-0x4a00

	if (a == -0x4a)
		printf("a promote\n");
	if (b == -0x4a00)
		printf("b promote\n");
}
//Integer lift example 2
void main()
{
	char c = 1;
	printf("%d\n", sizeof(c));
	printf("%d\n", sizeof(c+c));
	printf("%d\n", sizeof(!c));
}

Arithmetic conversion

If the operands of an operator are of different types, the operation cannot be performed unless one of the operands is converted to the type of the other operand. The following hierarchy is called ordinary arithmetic conversion.

long double
double
float
unsigned long int
long int
unsigned int
int

If the type of an operand ranks low in the above table, it must be converted to the type of another operand before performing the operation.

Note: arithmetic conversion should be reasonable, otherwise there will be some potential problems

float f = 3.14f;
int num = f; // Implicit conversion, there will be precision loss

Properties of the operator

There are three factors that affect the evaluation of complex expressions:

  1. operator precedence
  2. Associativity of operators
  3. Control evaluation order

Which two adjacent operators execute first depends on their priority order. If the two have the same priority, it depends on their combination.

In different compilers, the execution results of the following code may be different, which is mainly determined by the compiler's own mechanism. Because the calling order of functions cannot be determined by the priority of operators.
Example of problem code:

int fun()
{
	static int count = 1;
	return ++count;
}
void main()
{
	int answer;
	answer = fun() + fun() * fun();
	//From the priority of operands, we can only know which function is executed first and then add, but we can't know which function is executed first.
	printf("%d\n", answer);
}

Posted by pkallberg21 on Thu, 18 Nov 2021 03:29:40 -0800