Let's narrow the subject down to the 'C' case.

In case of implementing reusable library, sometimes we want to add some hidden information at the allocated memory used in the library. To achieve this, library may support special paired-interface. For example

    void* mylib_malloc(unsigned int size);
    void mylib_free(void* p);

To simplify discussion, let's assume that we want add just hidden 'int' value.
We can easily think two options.
- add hidden value to the end of allocated memory. -- (*1)
- add to the start of it. -- (*2)

But we cannot use (*1), because, in general, we cannot know size of memory that is allocated. Therefore there is no general way to access hidden value by address.
So, (*2) is only way we can use. Actually, this is general way to implement standard 'malloc' function, too.

then, memory block structure will be like this.

            returned value
             of 'mylib_malloc'
                 |
                 v
    +------------+-------------------
    | hidden-int | user-allocated
    +------------+-------------------

We should keep in mind these.
- Size of hidden value depends on data-align-constraint. That is, memory address of user-allocated-space should obey data-align-constraint. For example, in case of 32bit ARM, 4 byte data align is required. So, size of hidden value should be multiple of 4 to get 4-byte-aligned-address for user space.
- 'mylib_alloc/mylib_free' should make a pair. (Standard-free-function should not be used - it raises error.)

--- Sub-shell / Current shell ---

(*1)
    echo -e "aaa\nbbb\nccc\nddd" > tmp
    value=0;
    while read line; do
        value=$(expr $value + 1)
        echo $value
    done < tmp
    rm -f tmp
    echo "at last: $value"

    result:
    1
    2
    3
    4
    at last: 4

(*2)
    value=0
    echo -e "aaa\nbbb\nccc\nddd" | while read line; do
        value=$(expr $value + 1)
        echo $value
    done
    echo "at last: $value"

    result:
    1
    2
    3
    4
    at last: 0

It is interesting, isn't it? The main reason is, (*1) is executed in current shell. But (*2) is executed in sub-shell. In more detail, there is only one process(current shell) during run at (*1). But at (*2), there are three processes; current shell, process for 'echo' and process for 'while loop'.

--- Shell function ---

(*1)
    function func_name() {
        ...
    }

(*2)
    func_name() {
        ...
    }

(*2) is more portable than (*1). Bash supports both (*1) and (*2). But, dash - /bin/sh -> dash in Ubuntu - doesn't support (*1).

--- Syntax ---
'()' grouping and '{}' grouping is delicately different in it's syntax.

(echo 1; echo 2; exit 0) # OK
{ echo a; echo b; exit 1 } # syntax error
{ echo a; echo b; exit 1; } # OK

 
--- Test ---
'!' has higher priority than '-a' and '-o'.

Assume that there are two files; 'a' and 'b'

[ -r a -a -r b ] : TRUE
[ ( -r a -a -r b ) ] : syntax error
[ ( -r a ) -a ( -r b ) ] : syntax error
[ ! -r a -o -r c ] : FALSE
[ ! -r a -o -r b ] : TRUE

 
--- Replacement ---
'~' isn't replaced in "". So,

MYHOME=~ # OK
MYHOME="~" # it doesn't work as expected

 
--- Symbolic link ---
Assume following file structure.

/data/userA/
/data/userB/
/home/a (a -> /data/userA/)
/home/b (b -> /data/userB/)

Let's see the following test.

cd /home/
cd a
pwd
    -> '/home/a' is shown.
ls ..
    -> 'userA' and 'userB' are shown. -- (*a)
cd ..
pwd
    -> '/home' is shown -- (*b)
ls
    -> 'a' and 'b' are shown. -- (*c)
cd /home/
cd a
cp a.txt ../
    -> a.txt is created at '/data/' -- (*d)

As you can see, the way handling symbolic link is different among commands. In above test, 'cd' and 'pwd' work differently from 'ls' and 'cp'. Some commands - like 'cd' and 'pwd' - handle directory path of working directory but some - like 'cp' and 'ls' - doesn't.
Therefore, try to use 'absolute path' to avoid the case like this, if symbolic link is included in the directory path.

* We can use 'View.draw(Canvas cavans)' to draw the view on selected canvas manually. But, as documented, the view must do a full layout. See following example.

--- It doesn't work ---
TextView tv = new TextView(this);
tv.setLayoutParams(new LayoutParams(400, 400));
tv.setText("Test");
tv.draw(canvas);

--- It works ---
TextView tv = new TextView(this);
tv.layout(0, 0, 400, 400);
tv.setText("Test");
tv.draw(canvas);

'setLayoutParams' is not doing layout, but just setting parameters for layout. So, we should manually do layout - ex, calling 'layout' function. And then we can draw the view.

* In general, view's coordinate domain is user content area - excluding status bar area. But, in case of Popup, it includes status bar. For example, base origin of left and top value of function 'popup.showAtLocation(parent, NO_GRAVITY, left, top)' is top-left of LCD screen - Not user content area. So, popup shown by 'popup.showAtLocation(parent, NO_GRAVITY, 0, 0)' is partially covered by status bar.

* 'android:layout_weight' is only valid in LinearyLayout - It is natural.

* When array is passed from Java to native code, there are two opions - copy or not. If array size is small, this doesn't matter. But, in case of large array, this can be important. In Android-Eclair, array is never copied. So, developer don't worry about passing large-size-array to native. You can check this from the macro code "dalvik/vm/jni.c: GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)".

+ Recent posts