25-#和##操作符使用分析

注:博客中内容主要来自《狄泰软件学院》,博客仅当私人笔记使用。

测试环境:Ubuntu 10.10

GCC版本:4.4.5

一、#运算符

1)#运算符用于在预处理期将宏参数转换为字符串

2)#的转换作用是在预处理期完成的,因此只在宏定义中有效

3)编译器不知道#的转换作用(预编译期间行为)

4)用法

#define STRING(x) #x
printf("%s", STRING(Hello World!));
打印:Hello World!
实例分析
#运算符的基本用法
25-1.c

#include <stdio.h>
#define STRING(x) #x

int main()
{
    printf("%s\n", STRING(Hello World!));
    ptintf("%s\n", STRING(100));
    printf("%s\n", STRING(while));
    printf("%s\n", STRING(return));

    return 0;
}

操作:

1)gcc 25-1.c -o 25-1.out编译正确,打印结果:

Hello World!
100
while
return

2)注释掉头文件,预编译:gcc -E 25-1.c -o 25-1.i

# 1 "25-1.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1
# 1 "<command-line>" 2
# 1 "25-1.c"

int main()
{
    printf("%s\n", "Hello World!");
    printf("%s\n", "100");
    printf("%s\n", "while");    
    printf("%s\n", "return");

    return 0;
}
实例分析
25-2.c
#include <stdio.h>

/*
功能:打印调用的函数名,返回函数结果
知识点:逗号运算符、#运算符将宏参数或转换成字符串
*/
#define CALL(f, p)    (printf("Call function %s\n", #f, f(p)))

int square(int n)
{
    return n * n;
}

int func(int x)
{
    return x;
}

int main()
{
    int result = 0;

    result = CALL(square, 4);
    
    printf("result = %d\n", result);

    result = CALL(func, 10);

    printf("result = %d\n", result);

    return 0;
}

操作:

1)编译:gcc 25-2.c -o 25-2.out编译正确,运行结果:

Cakk function square
result = 16
Call function func
result = 10

2)注释掉头文件,预编译命令:gcc -E 25-2.c -o 25-2.i

# 1 "25-2.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1
# 1 "<command-line>" 2
# 1 "25-2.c"

int square(int n)
{
    return n * n;
}

int func(int x)
{
    return x;
}

int main()
{
    int result = 0;
    
    result = (printf("Call function %s\n", "square"), square(4));

    printf("result = %d\n", result);

    result = (printf("Call function %s\n", "fcun"), func(10));

    printf("result = %d\n", result);

    return 0;
}

二、##运算符

1)##运算符用于在预处理期粘连两个标识符

2)##的连接作用是在预处理期完成的,因此只在宏定义中有效

3)编译器不知道##的连接作用(再次强调和编译期无关)

4)用法

#define CONNECT(a, b) a##b
int CONNECT(a, 1)    //int a1;
a1 = 2;
实例分析
##运算符的基本用法
25-3.c

#include <stdio.h>
#define NAME(n) name##n

int main()
{
    int NAME(1);    //int name1;
    int NAME(2);    //int name2;

    NAME(1) = 1;
    NAME(2) = 2;

    printf("%d\n", NAME(1));    //1
    printf("%d\n", NAME(2));    //2

    return 0;
}

操作:

1)编译:gcc 25-3.c -o 25-3.out编译正确,打印结果:

1
2

2)注释掉头文件stdio.h,预编译:gcc -E 25-3.c -o 25-3.i

# 1 "25-3.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1
# 1 "<command-line>" 2
# 1 "25-3.c"

int main()
{
    int name1;
    int name2;

    name1 = 1;
    name2 = 2;

    printf("%d\n", name1);
    printf("%d\n", name2);

    return 0;
}
实例分析
##运算符的工程应用
25-4.c

#include <stdio.h>
/*
知识点:typedef、##粘连符
重命名结构体:typedef struct _tag_##type type;
为了方便定义结构体:struct _tag_##type
*/
#define STRUCT(type) typedef struct _tag_##type type:\
                     struct _tag_##type

STRUCT(Student)
{
    char* name;
    int id;
};

int main()
{
    Student s1;
    Student s2;
    s1.name = "s1";
    s1.id = 0;

    s2.name = "S2";
    s2.id = 1;

    printf("s1.name = %s\n", s1.name);
    printf("s1.id = %d\n", s1.id);
    printf("s2.name = %s\n", s2.name);
    printf("s2.id = %d\n", s2.id);

    return 0;
}

操作:

1)编译:gcc 25-4.c -o 25-4.out编译正确,打印结果:

s1.name = s1
s1.id = 0
s2.name = s2
s2.id = 1

2)预编译:gcc -E 25-4.c -o 25-4.i

# 1 "25-4.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1
# 1 "<command-line>" 2
# 1 "25-4.c"

typedef struct _tag_Student Student: struct _tag_Student
{
    char* name;
    int id;
};

int main()
{
    Student s1;
    Student s2;
    s1.name = "s1";
    s1.id = 0;

    s2.name = "s2";
    s2.id = 1;

    printf("s1.name = %s\n", s1.name);
    printf("s1.id = %d\n", s1.id);
    printf("s2.name = %s\n", s2.name);
    printf("s2.id = %d\n", s2.id);

    return 0;
}

小结:

1)#运算符用于在预处理期将宏参数转换为字符串

2)##运算符用于在预处理期粘连两个标识符

3)编译器不知道#和##运算符的存在

4)###运算符只在宏定义中有效

发布了40 篇原创文章 · 获赞 1 · 访问量 1757

猜你喜欢

转载自blog.csdn.net/piaoguo60/article/details/104070573