The first chapter covers the foundation of programming. This article focuses on section 1.6.1: arrays and pointers.
> > > Â 1.6.1 Arrays and Pointers
Arrays
(1) Array Declaration
We know that a single variable of a basic data type can only hold one piece of data, for instance:
Int data = 0x64;
But what if you want to store a set of integer data, such as 1, 2, and 3? At minimum, you'd need three separate variables—data0, data1, and data2. For example:
Int data0 = 1, data1 = 2, data2 = 3;
As data comes in various forms—characters, floats, and other numerical types—basic data types alone are insufficient. Can we construct more complex data types by combining and abstracting these primitive types? Yes, we can create an array to handle this situation.
Conceptually, the integers 1, 2, and 3 are all of the same data type. The commonality among data0, data1, and data2 lies in their shared data attribute, while their distinction comes from differing subscripts. Thus, we can abstract data0, data1, and data2 into a unified name and use subscripts to differentiate between them—data[0], data[1], and data[2]. Consider the following statement:
Int data[3]; // This is interpreted as data being an array of 3 integers
In this case, data[3] becomes an array composed of data[0], data[1], and data[2], which store the integers 1, 2, and 3. These elements can then be individually assigned:
Data[0] = 1, data[1] = 2, data[2] = 3;
Alternatively, you can declare and initialize an array in one step:
Int data[3] = {1, 2, 3};
In this context, data is often referred to as the array (variable) name, while data[0], data[1], and data[2] are considered individual variables. Therefore, an array essentially groups several variables of the same data type in an orderly fashion, assigns them a collective name, and distinguishes between them using subscripts.
Since arrays are built upon other types, C treats arrays as composite types. When declaring an array, the compiler requires you to specify the type of its elements—whether they're of type int, float, or another type. Furthermore, arrays can also contain other array types, creating multidimensional arrays.
(2) Subscripts and Variable Values
Consider an array type variable named data, which comprises variables data[0], data[1], and data[2] holding the integers 1, 2, and 3. Typically, each variable within an array is referred to as an array element. Array elements are sequentially numbered, and these numbers are known as subscripts of the array elements.
Due to the use of subscripts, the location of an array element in memory is uniquely determined. Subscripts always start at 0. The last element's subscript is the total number of elements minus one (in this case, 2). Hence, data[0] is called the first element, data[1] the second, and data[2] the third. This implies that all elements are stored consecutively in memory.
Intuitively, an array is a collection of pairs, each consisting of a subscript and a corresponding value—
The function Create(data, size) generates a new empty array of the appropriate size. Initially, each item in the array is undefined. The Retrieve operation accepts an array of data and a subscript index. If the subscript is valid, the operation returns the value associated with the subscript; otherwise, an error occurs. The Store operation accepts an array of data, a subscript index, and an item (the value to be stored), returning a new pair
Clearly, any constant expression of the int system can serve as an array element subscript. For example:
Int array[3+5]; // Valid
Int array['a']; // Int array[97];
The above definitions are valid because the constant expression representing the number of elements has a definite meaning at compile time, and a fixed-size space is explicitly allocated as defined by the variable.
Using symbolic constants enhances array flexibility. However, if you define an array like this:
Int n = 5;
Int array[n]; // Illegal
Standard C considers the number of array elements n as non-constant. Even though the compiler seems to "see" the value of n, int array[n] cannot determine the size of its space at compile time because the value of n could change during runtime. The proper way to define an array length using symbolic constants is as follows:
#define N 10
Int array[N];
You can modify the value of the constant N as needed.
Since the valid range of array element subscripts is 0 to N-1, data[N] does not exist. However, C does not check whether the subscript is out of bounds. Accessing an element beyond the array's end results in accessing memory unrelated to the array, which can lead to issues. Why does C allow this? It's due to C's trust in the programmer—disabling boundary checks allows faster execution. Compilers don't have to verify every subscript error, which would slow down the program. C assumes that programmers write correct code, leading to faster execution. Not all programmers meet this standard, though. Out-of-bounds access is a common beginner mistake, so always ensure your subscripts stay within reasonable limits.
(3) Address and Type of Variables
When data[0], data[1], and data[2] are used as operands for &, &data[0] is a pointer to data[0], &data[1] is a pointer to data[1], and &data[2] is a pointer to data[2]. The variables data[0], data[1], and data[2] are of type int, while &data[0], &data[1], and &data[2] are of type int *const, which is a pointer to a constant, commonly referred to as a constant pointer whose value cannot be modified. For example:
Int a;
Int * const ptr = &a;
Ptr = NULL; // Attempt to modify, compilation error
&a = NULL; // Attempt to modify, compilation error
Similarly, &data is a pointer to the variable data. What type is data?
According to the declaration of the variable, after extracting the identifier data, the remaining "int [3]" represents the type of data, which is typically interpreted as an array of three ints, referred to as an array type. The purpose is to inform the compiler how much memory to allocate—a block for three integers. The data type testing procedure is detailed in Listing 1.20.
Listing 1.20: Data Type Testing Program
1 #include
2
3 void f(int x);
4 int main(int argc, char *argv[])
5 {
6 int data[3];
7 f(data);
8 return 0;
9 }
The compiler warning, "function: 'int' differs in levels of indirection from 'int [3]'", indicates that the array variable data's type is not int but int[3], an array type. This design simplifies compiler development but makes it harder for beginners to grasp due to the ambiguity of concepts. Ideally, the array should be defined as:
Int [3] data;
That is, int is combined with [3]. What type is &data?
When data is an operand of &, &data is a pointer to data. Since data's type is int[3], &data is a pointer to the "array type int[3]" variable data, referred to as an array pointer. Its type is int(*)[3], a pointer to an int[3]. Why use parentheses to enclose the asterisk?
Without enclosing the asterisk in parentheses, "int(*)[3]" becomes "int*[3]", which is interpreted as an array of three pointers to int (type), following the compiler's grammar rules.
Is the type of &data "int(*)[3]"? An example of its verification procedure is shown in Listing 1.21.
Listing 1.21: &data Type Tester
1 #include
2 int main(int argc, char *argv[])
3 {
4 int data[3];
5 int b = &data;
6 return 0;
7 }
The compiler warning, "int differs in levels of indirection from int(*)[3]," indicates that the type of &data is indeed int(*)[3].
(4) sizeof(data)
When data is used as the operand of sizeof, it returns the total size of the entire array. Here, sizeof(data) equals 12, which is the size of 3 elements, 4×3=12 bytes. The system interprets "1" in &data+1 as an offset equivalent to the size of an array, making &data+1 the address of the next undefined storage space (out of bounds). In little-endian mode, the array is stored in memory as shown in Figure 1.10.
Figure 1.10 Â Array Storage
To locate the corresponding array element, a common approach is to calculate the address of an array element using "base address + offset of array." Here, the address of the first element &data[0] is called the base address, and the offset is the subscript multiplied by the size of each element sizeof(int). Assuming the address of the array element &data[0] is A and its actual address in memory is 0x22FF74, then the value of &data[1] is:
A + 1×sizeof(int) = (unsigned int)data + 4 = 0x22FF74 + 4 = 0x22FF78
The value of &data[2] is:
A + 2×sizeof(int) = (unsigned int)data + 8 = 0x22FF74 + 8 = 0x22FF7C
In fact, when writing data[i] in C, C translates it into a pointer to an int. Data is a pointer to data[0], and data+i points to data[i]. Regardless of the array's type, data+i is always equal to data[i], so *(data+i) equals data[i]. The corresponding test sample program is detailed in Listing 1.22.
Listing  1.22  Variable Address Test Program
1 #include
2 int main(int argc, char *argv[])
3 {
4 int data[3] Â = {1, 2, 3};
5 printf("%x, %x, %x, %x, %x", &data[0], &data[1], &data[2], &data, &data+1);
6 return 0;
7 }
The experiment shows that although &data[0] and &data are not of the same type, their values are equal. It also demonstrates that array elements are stored consecutively. Dividing the size of the array variable's memory by the size of the space occupied by an array element yields the number of array elements:
Int numData = sizeof(data) / sizeof(data[0]);
You can also use a macro definition to calculate the number of array elements:
#define NELEMS(data) (sizeof(data) / sizeof(data[0])
When an array is passed as a parameter to a function, all C function parameters must be declared within the function. However, no new storage space is allocated to the array inside the function. Clearly, if a function needs to know the size of a one-dimensional array, it must receive this information either as a function argument or via a global variable.
SVLEC Ethernet switches have 5 port and 8 port , IP 20 series have 5 or 8 RJ45 socket , with 100/1000 Mbps transmission speed and POE support , can be mounted on the rail . IP67 series have 8 M12 D code female port , with 10/100 MBit/s , wall mount and panel installation can widely used in CNC machines , Logistics and other areas .
Ethernet Switches,8 Port Ethernet Switch,5 Port Ethernet Switch,100Mbps Ethernet Switch, IP67 ethernet switch
Kunshan SVL Electric Co.,Ltd , https://www.svlelectric.com