本文主要讲解本人在开发过程中遇到的一些不同平台的差异的问题,已经使用的注意事项

BUFSIZ

此参数定义在stdio.h中,在 win 中有 512 个字节,在 linux 中有 8192 个字节。

  • Win
    1
    2
    /* Buffered I/O macros */
    #define BUFSIZ 512
  • Linux
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // stdio.h
    #ifndef BUFSIZ
    # define BUFSIZ _IO_BUFSIZ
    #endif

    // libio.h
    #define _IO_BUFSIZ _G_BUFSIZ

    // _G_config.h
    #define _G_BUFSIZ 8192

    __VA_ARGS__

__VA_ARGS__ 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有 gcc 支持。

实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。

  • Linux
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include<stdio.h>
    #define print_variable(...) printf(__VA_ARGS__)
    #define print_variable2(fmt, ...) printf(fmt, ##__VA_ARGS__)
    int main() {
    int b = 1;
    print_variable("%d=%d", b, 1);
    print_variable2("hel\n");
    return 0;
    }

    注意:在print_variable2中可以发现,使用__VA_ARGS__时多了两个##
    此处是为了防止只传一个参数的时候,print_variable2会编译出错。
    其中##的作用就像是将,删除一样,具体原因未知。

#

将参数转换为字符串。此处转换为字符串有两层含义:

  1. 如果传递的是带有值的变量名,那么字符串就是指变量名。
  2. 如果传递的是简单类型值,那么字符串的就是指简单类型转换为字符串的值。
  • Linux
    1
    2
    3
    4
    5
    6
    7
    8
    #include<stdio.h>
    #define P(A) printf("%s:%d\n", #A, A)
    int main() {
    int b = 1;
    P(b);
    P(1);
    return 0;
    }
    结果为:
    1
    2
    b:1
    1:1

##

将宏定义中的参数变成字符串连在一起。

  • Linux
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>
    #define STR(a) #a
    #define FUNC(a, b) a##b
    int main()
    {
    int a = 1, b = 2;
    char* ab = "Hello";
    printf(STR(a));
    printf("\n");
    printf(FUNC(a, b));
    return 0;
    }
    结果为:
    1
    2
    a
    Hello

C 中 AF_xxx 与 PF_xxx的区别

除了在 Unix/Linux 中存在一定区别外(在不同的版本中这两者有微小差别。对于 BSD,是 AF,对于 POSIX 是 PF。),其实是一样的。

只是在使用的时候,设置 socket 的时候使用 PF_xxx,设置 addr 的时候使用 AF_xxx。

例如:

1
2
int sockfd = socket(PF_LOCAL, SOCK_STREAM, 0);
adr_unix.sin_family = AF_LOCAL;

errorno 简述

在 Linux 中 api 函数发生异常时,一般会将 errno 变量(需 #include<errno.h>)赋一个整数值,用于推测出错原因。

由于不可能每次都去查询 errno.h 中的解释,可以通过以下的函数获取错误信息。

  • Linux

    • perror(): 用来将上一个函数发生错误的原因输出到标准错误(stderr),参数s 所指的字符串会先打印出,后面再加上错误原因 字符串
    • char *strerror(int errno): 将错误代码转换为字符串错误信息,可以将该字符串和其它的信息组合输出到用户界面。例如
      1
      fprintf(stderr,"error in CreateProcess %s, Process ID %d",strerror(errno),processID)
    • int strerror_r(int errnum, char *buf, size_t n): 将错误代码转换为字符串信息,并存储到大小为 n 大小的 buf 中。
    • printf("%m", errno)
  • Win

    • perror(): 与 Linux 同。
    • errno_t strerror_s(char * buf,rsize_t bufsz,errno_t errnum): 使用方式与strerror_r相同。
    • 其它相同

printf 自动连接字符串

目前在 Linux 与 Win 都测试了,printf 函数可以实现直接连接两个字符串。如下所示:

1
printf("hello"",error %d", 1);