210 likes | 357 Vues
This course, originally developed by Maj. Ron Smith and addressed by Dr. Alain Beaulieu, delves into the vital concepts of pointers, variables, and functions in the context of real-time operating systems. It explores the efficiency of passing references versus values, the dynamics of memory allocation, and the flexibility of using void pointers. The course emphasizes the importance of initializing pointers and demonstrates how functions can accept and return pointers, illustrating their applicability through practical examples and code snippets.
E N D
EE551 Real-Time Operating Systems Pointers and Pointers to Functions Course originally developed by Maj Ron Smith
Addresses • We know that we use variables to identify our data within our programs • We assigned an identifier (a symbol) to our data in a declaration, and then we used this variable to manipulate this data • The compiler uses these identifiers to resolve the symbolic location of a variable to an address… a logical address Dr Alain Beaulieu
Addresses • When we talk about functions, we know that passing a reference to a variable instead of passing its value can be more efficient • That is because a function can access and modify “outside” data directly; saving function calls overhead • Imagine a loop where you calculate the square of all the elements in an array • This direct access to variables has a lot more uses Dr Alain Beaulieu
Addresses • Addresses…but modern operating systems load programs where they want into physical memory. • For one execution, variable a might be at physical address 01A4:F4A1 and at the next execution the same variable could be at 34BC:4DA1 • So although we want the power of using addresses, we do not want to loose the flexibility afforded by symbolic names Dr Alain Beaulieu
Addresses – memory model ??? Logical Physical Symbolic 0000 #define stuff … void main() { … int a; … } 00FF … Compile and link Load Dr Alain Beaulieu
Pointer variables Symbolic Logical … void main() { … int a = 145; int b = 0; int *p; // a pointer … p = &a; *p=99; //indirection b = *p; //b = value of variable //pointed to by p }//main a 145 12500 b 0 46798 p ??? 57109 Dr Alain Beaulieu
Pointer variables Symbolic Logical … void main() { … int a = 145; int b = 0; int *p; // a pointer … p = &a; *p=99; //indirection b = *p; //b = value of variable //pointed to by p }//main a 145 12500 b 0 46798 p 12500 57109 Dr Alain Beaulieu
Pointer variables Symbolic Logical … void main() { … int a = 145; int b = 0; int *p; // a pointer … p = &a; *p=99; //indirection b = *p; //b = value of variable //pointed to by p }//main a 99 12500 b 0 46798 p 12500 57109 Dr Alain Beaulieu
Pointer variables Symbolic Logical … void main() { … int a = 145; int b = 0; int *p; // a pointer … p = &a; *p=99; //indirection b = *p; //b = value of variable //pointed to by p }//main a 99 12500 b 99 46798 p 12500 57109 Dr Alain Beaulieu
Pointer variables - init • A pointer like any other variable in C has no automatic initialization • It contains garbage • More than any other variables, you should initialize all your pointers explicitly • You can initialize a pointer using a real address: int a; int *p; p = &a; • Or int *p = NULL; Dr Alain Beaulieu
Pointers meet functions • Functions do not only accept pointers they can return them as well!!! • The next example shows a function that returns a pointer to the smaller of two values that were passed to it • The pointer (address) is then stored in a pointer variable in the caller Dr Alain Beaulieu
void pointers • C does not allow for comparison or mixing of pointer types • There is one exception to this rule: • the void pointer • In C the void pointer is a generic or universal pointer that can be used where the type of data is not known at compile time • MicroC/OS uses a lot of void Pointers… To be flexible. Dr Alain Beaulieu
void pointers • So why use a void pointer? • Dynamic memory allocation. When you ask for memory, C will return you a pointer for the memory that you requested. This pointer is a void pointer • Because the function that grants you the memory has no idea of the type you are using //malloc returns an address to an empty block of memory void *malloc(int size); //as it is defined in C int *iPtr; … iPtr = (int *)malloc(10 * sizeof(int)); //casting Dr Alain Beaulieu
void pointers • You would declare a void pointer like this: void *pointerToVoid; • Because the pointer does not point to any type of variable, it cannot be dereferenced in a statement int myVar; myVar = *pointerToVoid; //error! *pointerToVoid = myVar; //error! Dr Alain Beaulieu
void pointers - casting • We can use casting with pointer types int *pInt; char *pChar; void *pVoid; … pInt = pChar; //compile error pInt = (int *) pVoid; //good pChar = (char *) pVoid; //good pInt = (int *) pChar; //valid but not logical! Dr Alain Beaulieu
Pointers to functions • Functions occupy space in memory just like any other code entities, such as variables, arrays and structures • The name of a function is a pointer constant similar to the name of an array • It is therefore possible to have pointer variables that can point to functions • Just like it is possible to have pointer variables that point to arrays Dr Alain Beaulieu
Pointers to functions • A declaration syntax for a pointer to a function is similar to a prototype declaration • It starts with the type of the function (what the function returns), • the name of the pointer variable in parentheses and, • the parameter types in parentheses : int (*fpInts) (int, int); void (*fpConvert) (char); char *(*fpString) (char *,char *); Dr Alain Beaulieu
Pointers to functions • One of the main uses for a function pointer is to pass the name of a function (its address) to a task manager • The pointer to function is therefore used to start tasks in some systems • One of the main reasons for using pointers to functions, is that the name of a task function may not be known before runtime • The flexibility afforded by pointers to functions is key to our ability to build dynamic systems Dr Alain Beaulieu
We can pass a pointer to a function as a parameter to another function #include <stdio.h> void ExecUnit(void (*fp) (int, int), int, int); void Difference (int a, int b); void main(void) { ExecUnit(Difference, 5, 5); getchar(); } void Difference (int a, int b) { printf("Difference is: %d", a-b); return; } void ExecUnit(void (*fp) (int, int), int a, int b) { (*fp)(a,b); return; } Dr Alain Beaulieu
MicroC/OS task creation Definition INT8U OSTaskCreateExt (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio, INT16U id, OS_STK *pbos, INT32U stk_size, void *pext, INT16U opt) Call OSTaskCreateExt(AppStartTask, (void *)0, (OS_STK *)&AppStartTaskStk[APP_TASK_START_STK_SIZE - 1], APP_TASK_START_PRIO, APP_TASK_START_PRIO, (OS_STK *)&AppStartTaskStk[0], APP_TASK_START_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); AppStartTask(void *data){…} Dr Alain Beaulieu