210 likes | 345 Views
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
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