Emum (enumeration)
Enumeration is a basic data type in C. It can make data more concise and readable.
Enumeration grammar is defined in the following format:
enum enumeration name {enumeration element 1, enumeration element 2,...};
For example, if there are 7 days in a week, instead of enumeration, we need to use #define to define an alias for each integer:
#define MON 1 #define TUE 2 #define WED 3 #define THU 4 #define FRI 5 #define SAT 6 #define SUN 7
This seems like a lot of code, so let's look at how enumeration is used:
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };
Does this look simpler?
Note: The default value for the first enumerated member is 0 of integer type, and the value for subsequent enumerated members is 1 on the previous member.In this example, we define the value of the first enumeration member as 1, the second as 2, and so on.
You can change the value of an enumeration element when defining an enumeration type:
enum season {spring, summer=3, autumn, winter};
Enumeration element with no specified value whose value is the previous element plus 1.That is, spring has a value of 0, summer has a value of 3, autumn has a value of 4, winter has a value of 5
Definition of enumeration variable
So let's just declare the enumeration type, so let's see how to define the enumeration variable.
There are three ways we can define enumeration variables
1. Define the enumeration type before defining the enumeration variable
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN }; enum DAY day;
2. Define enumeration variables while defining enumeration types
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN } day;
3. Omit the enumeration name and define the enumeration variable directly
enum { MON=1, TUE, WED, THU, FRI, SAT, SUN } day;
Example
#include<stdio.h> enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN }; int main() { enum DAY day; day = WED; printf("%d",day); // 3 return 0; }
In C, enumeration types are treated as ints or unsigned int s, so it is impossible to traverse them according to the C language specification.
However, in some special cases, enumeration types must be continuous to allow conditional traversal.
The following example uses for to traverse elements of an enumeration:
#include<stdio.h> enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN } day; int main() { // Traverse Enumeration Elements for (day = MON; day <= SUN; day++) { printf("Enumeration Elements:%d \n", day); } }
The output from the above example is:
Enumerated elements: 1
Enumerated elements: 2
Enumerated elements: 3
Enumeration elements: 4
Enumeration elements: 5
Enumerated Elements: 6
Enumerated Elements: 7
The following enumeration types are discontinuous and cannot be traversed.
enum { ENUM_0, ENUM_10 = 10, ENUM_11 };
Use of enumeration in switch:
#include <stdio.h> #include <stdlib.h> int main() { enum color { red=1, green, blue }; enum color favorite_color; /* ask user to choose color */ printf("Please enter your favorite color: (1. red, 2. green, 3. blue): "); scanf("%d", &favorite_color); /* Output Results */ switch (favorite_color) { case red: printf("Your favorite color is red"); break; case green: printf("Your favorite color is green"); break; case blue: printf("Your favorite color is blue"); break; default: printf("You didn't choose your favorite color"); } return 0; }
The output from the above example is:
Please enter your favorite color: (1. red, 2. green, 3. blue):1
Your favorite color is red
Convert integers to enumerations
The following example converts an integer to an enumeration:
#include <stdio.h> #include <stdlib.h> int main() { enum day { saturday, sunday, monday, tuesday, wednesday, thursday, friday } workday; int a = 1; enum day weekend; weekend = ( enum day ) a; //Type Conversion //weekend = a; //error printf("weekend:%d",weekend); return 0; }
The output from the above example is:
weekend:1
Pointer
With pointers, you can simplify the execution of some C programming tasks, as well as some tasks, such as dynamic memory allocation, that cannot be performed without pointers.
Each variable has a memory location, and each memory location defines an address that can be accessed using the hyphen (&) operator, which represents an address in memory.See the ex amp le below, which outputs the address of the variable defined:
#include <stdio.h> int main () { int var1; char var2[10]; printf("var1 Address of variable: %p\n", &var1 ); printf("var2 Address of variable: %p\n", &var2 ); return 0; }
When the above code is compiled and executed, it produces the following results:
Address of var1 variable: 0x7fff5cc109d4
Address of var2 variable: 0x7fff5cc109de
From the example above, we learned what a memory address is and how to access it.Next let's see what a pointer is.
What is a pointer?
A pointer is a variable whose value is the address of another variable, that is, the direct address of the memory location.Like other variables or constants, you must declare other variable addresses before using pointers to store them.The general form of a pointer variable declaration is:
type *var-name;
Here, type is the base type of a pointer, it must be a valid C data type, and var-name is the name of the pointer variable.The asterisk* used to declare a pointer is the same as the asterisk used in multiplication.However, in this statement, an asterisk is used to specify that a variable is a pointer.The following is a valid pointer declaration:
int *ip; /* An integer pointer */ double *dp; /* A double pointer */ float *fp; /* A floating-point pointer */ char *ch; /* A character pointer */
All actual data types, whether integer, float, character, or other, have the same type of value for the pointer, which is a long hexadecimal number representing the memory address.
The only difference between pointers of different data types is that they point to different data types of variables or constants.
How to use the pointer?
When using a pointer, you frequently do the following: define a pointer variable, assign the address of the variable to the pointer, and access the value of the address available in the pointer variable.These return the values of variables at the address specified by the operand by using the unary operator *****.The following examples cover these operations:
#include <stdio.h> int main () { int var = 20; /* Declarations of Actual Variables */ int *ip; /* Declaration of pointer variable */ ip = &var; /* Store var's address in pointer variable */ printf("Address of var variable: %p\n", &var ); /* Address stored in pointer variable */ printf("Address stored in ip variable: %p\n", ip ); /* Access values using pointers */ printf("Value of *ip variable: %d\n", *ip ); return 0; }
When the above code is compiled and executed, it produces the following results:
Address of var variable: bffd8b3c Address stored in ip variable: bffd8b3c Value of *ip variable: 20
NULL pointer in C
Assigning a NULL value to a pointer variable is a good programming practice when declaring variables without an exact address.A pointer assigned a NULL value is called a null pointer.
The NULL pointer is a constant with a value of zero defined in the standard library.See the following program:
#include <stdio.h> int main () { int *ptr = NULL; printf("ptr The address is %p\n", ptr ); return 0; }
When the above code is compiled and executed, it produces the following results:
ptr's address is 0x0
On most operating systems, programs do not allow access to memory with address 0 because it is reserved by the operating system.However, memory address 0 is particularly important because it indicates that the pointer does not point to an accessible memory location.By convention, however, if the pointer contains a null value (zero value), it is assumed that it does not point to anything.
To check for a null pointer, you can use the if statement as follows:
if(ptr) /* Complete if p is not empty */ if(!ptr) /* If p is empty, complete */
C Pointer Details
In C, there are many pointer-related concepts.Here are some important pointer-related concepts that C programmers must be aware of:
concept | describe |
---|---|
pointer arithmetic | Four arithmetic operations can be performed on pointers: ++, --, +, - |
Pointer Array | You can define an array to store pointers. |
Pointer to pointer | C Allows pointers to the pointer. |
Pass Pointer to Function | Pass parameters by reference or address so that they are changed in the calling function. |
Return pointer from function | C allows functions to return pointers to local variables, static variables, and dynamic memory allocations. |
Arithmetic Operator of Pointer
The C pointer is a numeric address.Therefore, you can perform arithmetic operations on the pointer.Four arithmetic operations can be performed on the pointer: ++, --, +, -.
Every time the code is compiled, the location of the memory stored changes, so to observe incremental (subtractive) changes, you can only compile it in one source code, not in two comparisons, where the difference between the two next integer values is four binary bits
Increment a pointer
We like to use pointers instead of arrays in our programs because variable pointers can be incremented, but arrays cannot be incremented, and arrays can be seen as a pointer constant.The following program increments the variable pointer to access each element of the array sequentially:
#include <stdio.h> const int MAX = 3; int main () { int var[] = {10, 100, 200}; int i, *ptr; /* Array address in pointer */ ptr = var; for ( i = 0; i < MAX; i++) { printf("Storage address: var[%d] = %p\n", i, ptr ); printf("Stored value: var[%d] = %d\n", i, *ptr ); /* Move to Next Location */ ptr++; } return 0; }
When the above code is compiled and executed, it produces the following results:
Storage address: var[0] = bf882b30
Stored value: var[0] = 10
Storage address: of var[1] = bf882b34
Stored value: var[1] = 100
Storage address: of var[2] = bf882b38
Stored value: var[2] = 200
Decrease a pointer
Similarly, the pointer is decremented by subtracting the value from the number of bytes of its data type as follows:
#include <stdio.h> const int MAX = 3; int main () { int var[] = {10, 100, 200}; int i, *ptr; /* The address of the last element in the pointer */ ptr = &var[MAX-1]; for ( i = MAX; i > 0; i--) { printf("Storage address: var[%d] = %x\n", i-1, ptr ); printf("Stored value: var[%d] = %d\n", i-1, *ptr ); /* Move to Next Location */ ptr--; } return 0; }
When the above code is compiled and executed, it produces the following results:
Storage address: var[2] = 518a0ae4
Stored value: var[2] = 200
Storage address: var[1] = 518a0ae0
Stored value: var[1] = 100
Storage address: var[0] = 518a0adc
Stored value: var[0] = 10
Pointer comparison
Pointers can be compared using relational operators, such as==, <and>.If p1 and p2 point to two related variables, such as different elements in the same array, then p1 and p2 can be compared in size.
The following program modifies the above example by incrementing the variable pointer as long as it points to an address less than or equal to the address of the last element of the array &var[MAX-1]:
#include <stdio.h> const int MAX = 3; int main () { int var[] = {10, 100, 200}; int i, *ptr; /* Address of the first element in the pointer */ ptr = var; i = 0; while ( ptr <= &var[MAX - 1] ) { printf("Address of var[%d] = %p\n", i, ptr ); printf("Value of var[%d] = %d\n", i, *ptr ); /* Point to the previous location */ ptr++; i++; } return 0; }
When the above code is compiled and executed, it produces the following results:
Address of var[0] = bfdbcb20
Value of var[0] = 10
Address of var[1] = bfdbcb24
Value of var[1] = 100
Address of var[2] = bfdbcb28
Value of var[2] = 200
Pointer Array
Let's start with an example that uses an array of three integers:
#include <stdio.h> const int MAX = 3; int main () { int var[] = {10, 100, 200}; int i; for (i = 0; i < MAX; i++) { printf("Value of var[%d] = %d\n", i, var[i] ); } return 0; }
When the above code is compiled and executed, it produces the following results:
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200
There may be a case where we want to have the array store point to an int or char or other data type.The following is a declaration of an array of pointers to integers:
int *ptr[MAX];
Here, ptr is declared as an array consisting of MAX integer pointers.Therefore, each element in the ptr is a pointer to the int value.The following example uses three integers, which are stored in an array of pointers as follows:
#include <stdio.h> const int MAX = 3; int main () { int var[] = {10, 100, 200}; int i, *ptr[MAX]; for ( i = 0; i < MAX; i++) { ptr[i] = &var[i]; /* Addresses assigned to integers */ } for ( i = 0; i < MAX; i++) { printf("Value of var[%d] = %d\n", i, *ptr[i] ); } return 0; }
When the above code is compiled and executed, it produces the following results:
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200
You can also store a list of strings with an array of pointers to the characters as follows:
#include <stdio.h> const int MAX = 4; int main () { const char *names[] = { "Zara Ali", "Hina Ali", "Nuha Ali", "Sara Ali", }; int i = 0; for ( i = 0; i < MAX; i++) { printf("Value of names[%d] = %s\n", i, names[i] ); } return 0; }
When the above code is compiled and executed, it produces the following results:
Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali
Pointer to pointer
A pointer to a pointer is a form of multilevel indirect addressing, or a chain of pointers.Typically, a pointer contains the address of a variable.When we define a pointer to a pointer, the first pointer contains the address of the second pointer and the second pointer points to the location containing the actual value.
A pointer variable that points to a pointer must be declared with two asterisks in front of the variable name.For example, the following declares a pointer to an int-type pointer:
int **var;
When a target value is indirectly pointed to by one pointer to another, accessing the value requires two asterisk operators, as shown in the following example:
#include <stdio.h> int main () { int var; int *ptr; int **pptr; var = 3000; /* Get the address of var */ ptr = &var; /* Use Operator &Get Address of ptr */ pptr = &ptr; /* Get value using pptr */ printf("Value of var = %d\n", var ); printf("Value available at *ptr = %d\n", *ptr ); printf("Value available at **pptr = %d\n", **pptr); return 0; }
When the above code is compiled and executed, it produces the following results:
Value of var = 3000
Value available at *ptr = 3000
Value available at **pptr = 3000
Pass Pointer to Function
C allows you to pass a pointer to a function by simply declaring the function parameter as a pointer type.
In the following example, we pass an unsigned long pointer to the function and change the value within the function:
#include <stdio.h> #include <time.h> void getSeconds(unsigned long *par); int main () { unsigned long sec; getSeconds( &sec ); /* Output Actual Value */ printf("Number of seconds: %ld\n", sec ); return 0; } void getSeconds(unsigned long *par) { /* Get the current number of seconds */ *par = time( NULL ); return; }
When the above code is compiled and executed, it produces the following results:
Number of seconds :1294450468
Functions that accept pointers as parameters can also accept arrays as parameters, as shown below:
#include <stdio.h> /* Function declaration */ double getAverage(int *arr, int size); int main () { /* Integer array with five elements */ int balance[5] = {1000, 2, 3, 17, 50}; double avg; /* Pass a pointer to the array as a parameter */ avg = getAverage( balance, 5 ) ; /* Output Return Value */ printf("Average value is: %f\n", avg ); return 0; } double getAverage(int *arr, int size) { int i, sum = 0; double avg; for (i = 0; i < size; ++i) { sum += arr[i]; } avg = (double)sum / size; return avg; }
When the above code is compiled and executed, it produces the following results:
Average value is: 214.40000
Return pointer from function
You must declare a function that returns a pointer, as follows:
int * myFunction() { }
In addition, C does not support returning the address of a local variable when a function is called unless a local variable is defined as a static variable.
Looking at the function below, it generates 10 random numbers and returns them using the array name that represents the pointer (that is, the address of the first array element), as follows:
#include <stdio.h> #include <time.h> #include <stdlib.h> /* Functions to generate and return random numbers */ int * getRandom( ) { static int r[10]; int i; /* Set Seed */ srand( (unsigned)time( NULL ) ); for ( i = 0; i < 10; ++i) { r[i] = rand(); printf("%d\n", r[i] ); } return r; } /* To call the main function of the function defined above */ int main () { /* A pointer to an integer */ int *p; int i; p = getRandom(); for ( i = 0; i < 10; i++ ) { printf("*(p + [%d]) : %d\n", i, *(p + i) ); } return 0; }
When the above code is compiled and executed, it produces the following results:
1523198053 1187214107 1108300978 430494959 1421301276 930971084 123250484 106932140 1604461820 149169022 *(p + [0]) : 1523198053 *(p + [1]) : 1187214107 *(p + [2]) : 1108300978 *(p + [3]) : 430494959 *(p + [4]) : 1421301276 *(p + [5]) : 930971084 *(p + [6]) : 123250484 *(p + [7]) : 106932140 *(p + [8]) : 1604461820 *(p + [9]) : 149169022
Reference from: https://www.runoob.com/cprogramming/c-tutorial.html