Showing posts with label C. Show all posts
Showing posts with label C. Show all posts

Monday, September 15, 2008

uclibc && nptl

不经意间发现自己使用的uclibc rpm包是带有nptl的. 于是上网查了一下这个nptl的含义.

具体可以看:
Linux threading models compared: LinuxThreads and NPTL
http://www.ibm.com/developerworks/linux/library/l-threading.html

glibc已经默认使用 NPTL. 而uclibc现在官方版本还是使用的linuxthread. 要使用nptl,则需要下载nptl分支:
svn://uclibc.org/branches/uClibc-nptl.

weak symbol

nm的manual里的说明:
When a  weak  defined symbol is linked with a normal defined symbol, the normal defined symbol is used with no error.  When a weak undefined symbol is linked and the symbol is not defined,  the  value of  the  symbol is determined in a system-specific manner without error.  On some systems, upper-case indicates that a default value has been specified.

网上其它有关的说明:
weak symbols can very well exist many or zero times. This will not cause any problem. If no symbol is found, a null one is provided. In case many symbols are found, the first one is taken and used by everybody.
(http://proj-gaudi.web.cern.ch/proj-gaudi/tricks/dynamic_cast.php)

测试程序:
说明:
  1. null为空,固打印了"not found null".
  2. strong函数的定义一处为weak,一处为strong,则链接器选用后者
  3. weak函数的定义两处都为weak,则链接器选用链接器所看到的第一个weak. (固更改链接命令o文件的位置即可得到不同的效果)
  4. 该测试只针对静态链接,对于动态链接效果怎么还末知
--------------------------------------------------
weak.c
--------------------------------------------------
extern void null() __attribute__((weak));
extern void strong() __attribute__((weak));
extern void weak() __attribute__((weak));

void strong()
{
    printf("false strong\n");
}

void weak()
{
    printf("first weak\n");
}

main()
{
    if(!null)
        printf("not found null \n");
    
    strong();
    weak();
}

--------------------------------------------------
strong.c
--------------------------------------------------
void strong()
{
    printf("true strong\n");
}

extern void weak() __attribute__((weak));
void weak()
{
    printf("second weak\n");
}

--------------------------------------------------
Makefile
--------------------------------------------------
.PHONY:clean

CFLAGS := -g -O0

%.o:%.c
    gcc $(CFLAGS) -o $@ -c $^
weak:  weak.o strong.o
#weak:   strong.o weak.o
    gcc $^ -o $@

weak.o: weak.c

strong.o: strong.c

clean:
    rm *.o

--------------------------------------------------
output:
--------------------------------------------------
[dybbuk@localhost tmp]$ ./weak
not found null
true strong
first weak
[dybbuk@localhost tmp]$ nm weak.o
00000028 T main
         w null
         U puts
00000000 W strong
00000014 W weak
[dybbuk@localhost tmp]$ nm strong.o
         U puts
00000000 T strong
00000014 W weak

Macros with a Variable Number of Arguments

Macros with a Variable Number of Arguments.
================================================

In ISO C99, a macro with a variable number of arguments can be defined.

example:
    #define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)

this macro has two parameter:format and ..., as __VA_ARGS__ stands for ... . So the invocation of this macro shall have two arguments acording to ISO C.

So the statement below is invalid.
    debug ("A message");    //only one argument
and it should be:
    debug ("A message",);   //an empty argument

But under GUN C, it is valid.

In the above examples, the compiler would complain though since the expansion of the macro still has the extra comma after the format string. (a error)

To help solve this problem, CPP behaves specially for variable arguments used with the token paste operator, `##'.  If instead you write

    #define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)

and if the variable arguments are omitted or empty, the `##' operator
causes the preprocessor to remove the comma before it.


And under GNU C, a more readabel way to refer variabel arguments.

    #define debug(format, args...) fprintf (stderr, format, args).


See gcc info section 5.14 'Macros with a Variable Number of Arguments' for more information.

test code:

#include <stdio.h>

#define DEVICE_NAME "test"
#define dprintk(fmt, ...) \
    do{ \
        if(1) printf(DEVICE_NAME ": " fmt, \
                 ## __VA_ARGS__); \
    }while(0)

#define dprintk1(fmt, ...) \
    do{ \
        if(1) printf(DEVICE_NAME ": " fmt, \
                 __VA_ARGS__); \
    }while(0)

/* 该宏也可以这样实现. 但其实这里回避了问题. 问题的引入是建立在可变参数部分为可以为空的基础上的,函数的可变参数就是这样的*/
#define dprintk2(...) \
    do{ \
        if(1) printf(DEVICE_NAME ": " __VA_ARGS__); \
    }while(0)


int main(void)
{
    dprintk("abc%d\n", 123);
    dprintk("abc\n");
#if 0
    dprintk1("abc%d\n", 123);
    dprintk1("abc\n");//test.c:29: error: expected expression before ')' token

#endif
    dprintk2("abc%d\n", 123);
    dprintk2("abc\n");

    return 0;
    
}