(转载)C语言的UNIX界面中两个版本的open函数

(转载)http://blog.chinaunix.net/uid-53564-id-2098830.html

unix 的 man page显示了下面的open函数原型:
    int open(const char *pathname, int flags);
    int open(const char *pathname, int flags, mode_t mode);

    它提示我们有两个版本的open函数, 你用两个参数调用它就调用两个参数的版
    本, 给三个参数就调用三个参数的版本, 似乎很神奇.

    这样的写法给人以假象.

    K&R的bible 里8.3节讲UNIX接口的OPEN函数, 也没有提到这点:
===========================
To open an existing file for reading,
fd = open(name, O_RDONLY,0);
The perms argument is always zero for the uses of open that we will discuss.
===========================
    实际上在这种情况下第三个参数是多余但无害的.

    问题是, 这是C语言, 它没有C++的overload机制, 一个函数的签名是不包括参
    数部分的, 编译器如何实现? 编译器对名为open的函数特别对待? 可能性不大
    .

    曾经有段时间我还肤浅地对人说过, 其实C语言中就有了C++的overload机制的
    原型, UNIX的open 系统调用就有两个参数的版本.

    然而, 这只是一种假象.

    open的真正原型是:
    extern int open (__const char *__file, int __oflag, ...) 
    它是变参函数.
    当 __oflag中有 O_CREAT时, 才会需要后面的一个参数. 然而open的实现却不
    象printf 那样表现出可传递参数在实用中的多变性. 它只有两种真正有用的
    可能性: 2个参数或3个参数.

    由于原型的机制, 使得C语言没有办法阻止你写多于3个的参数, 只不过,
    open的实现不会理会你传递给它的那些多余的参数, 而函数调用的参数传递机
    制又会正确地消除你额外传递的垃圾参数而引起的堆栈开销. 所以, 并无害
    处. 但下面的写法是正确的:

    open("abc.txt", O_RDONLY, S_IRWXU);
    因为第二个参数中没有 O_CREAT, 所以open的实现不会去检查第三个参数.
    而
    open("abc.txt", O_WRONLY | O_CREAT, S_IRWXU, 1, 2, "asdf");
    这样的写法也是合法的. gcc 加了参数-Wall也没有给出任何警告.

    这正如 printf("%d", 1 ,2 ,3 , "adf" );
    完全合法一样, 只不过 gcc特别为printf作了考虑, 它会用内窥镜看到printf
    的内部, 深入其五脏六腑做检查, 第一个格式化字串内的每个格式转换说明符
    与后面的参数是否类型匹配. 你调用printf时搞错了这个gcc是会有提醒的,
    前提是你用了-Wall 参数.

原文地址:https://www.cnblogs.com/Robotke1/p/3076280.html