At first glance, UCOS's osmemcreate code, feels a bit strange, for example, to force the pointer to the address of the pointer to the pointer to the address? What is the pointer to the post-conversion pointer?
void osmemcreate (os_mem *p_mem, cpu_char *p_name, void *p_addr, os_mem_qty n_ Blks, os_mem_size blk_size, os_err *p_err) {#if os_cfg_arg_chk_en > 0u cpu_data Align_msk; #endif os_mem_qty i; Os_mem_qty loops; cpu_int08u *p_blk; void **p_link;
...
P_link = (void * *) p_addr; /* Create linked list of free memory blocks * /p_blk = (cpu_int08u *) p_addr; Loops = n_blks-1u; for (i = 0u; i < loops; i++) { p_blk + = blk_size; *p_link = (void *) p_blk; /* Save Pointer to NEXT block in current block * /P_link = (void * *) (void *) p_blk; /* Position to NEXT block * /} *p_link = (void *) 0; /* Last memory block points to NULL */
(1), P_link = (void * *) p_addr; The P_ADDR value (that is, the address) is assigned to P_link, but the type is different, so cast.
(2), p_blk = (cpu_int08u *) p_addr; Casts, because P_ADDR is a void* parameter, any type of pointer.
(3), loops = n_blks-1u; Number of Cycles
(4), for (i = 0u; i < loops; i++) {//Loop
(5), p_blk + = blk_size; Add an address to a block space size
(6), *p_link = (void *) p_blk; The increment of the address, assigned to *p_link, that is written to the * (P_addr + blk_size) array, because, in (1) the P_ADDR address to the P_link.
(7), P_link = (void * *) (void *) p_blk; P_BLK, is the cpu_int08u * type pointer, so first cast to (void *) any type, and then, with (void * *) cast, with 1;
(8),}//Cycle end
(9), *p_link = (void *) 0; Null is assigned at the end of the list.
Here, **p_link meaningless, because *p_link equals * (p_addr + loops * blk_size), that is, the value of the array, what is the **p_link (* value)? If this value is exactly 32-bit and the requested space, such as 0x12345678, then **p_link, maybe it will make sense?
Also, since the **p_link, have not been used to, whether the use of one-level hands on the line? No need to use level two pointers?
So I did some tests with Xcode, as follows:
1. Traditional textbook usage, C-B->a
2, imitate the method of Ucos, b[0]= (address of a), b[1]= (address +3 of a).
2-1, found that there is a problem, adjusted to find, any type of pointer void *, self-increment, only increase by 1?
2-2, try the next address, add a pointer size, you can. Here, sizeof (void *) = sizeof (long int *) = 8. Tested with Xcode from the Mac.
3, the same imitation ucos, different from 2, pointer types are used long int *, without void *.
3-1, and 2 instead, the self-increment with the pointer is right.
3-2, and 2 instead, adding a pointer size is wrong.
4, later, think, since Ucos, with pointers, but all useless to **p_link, only use the first level of pointers, then I can p_link all parameters are added *, into the use of **p_link, and *p_link?
The result was wrong at first. Compile no problem, syntax is not wrong, however, P_p_b does not point to any address, cannot assign a value to *p_p_b.
5, the modification of 4, and ucos the same as the use of pointers, **p_p_b equivalent to **p_link. Use **p_p_b to modify the outer array, use P_p_b to point to the address of the continuously increasing outer array, and do not need to repeat p_p_b = &p_b (UCOS writing needs, see (7), because, UCOS, equivalent to use a first-level pointer, address change, need to re-assign address, and, Here the level two pointer points to a first-level pointer, a level change, and a level two track.
6, then fine think, since ucos only use the effect of a first-level pointer. Then whether I can use a level 1 pointer directly. (Here is wrong, the original effect should be p_b_1++, similar to ucos, need for constant p_b_2 = p_b_1)
At this point, the end.
Embedded: pointer pointers, linked lists, UCOS osmemcreate.