C语言高级特性

简介

        文章借鉴,以及本人的一些理解和发现。

C语言高级编程系列_hello_courage的博客-CSDN博客_c语言高级编程

#与##

C语言中"#"和"##"的用法_flist的博客-CSDN博客_c语言#的用法

#可以将符号转化为定义的字符串,##用于连接合并字符串

#define STR(s)     #s
#define CONS(a,b)  int(a##e##b)
int main()
{
   printf(STR(vck));           // 输出字符串"vck"
   printf("%d\n", CONS(2,3));  // 2e3 输出:2000
   return 0;
}
#include <stdio.h>
#define __stringfy(x) #x
int main(int argc, char* argv[]) 
{
    printf("%s",__stringfy(AA));
    return 0;
}

宏函数 

可参照

面试常问的16个C语言问题,你全会吗?

求最小值的宏:#define min(x,y) x > y? y: x 中的陷阱,慎用_暴躁的野生猿的博客-CSDN博客

GUN编译器可以编译宏函数,VS不行

宏函数几乎可以实现模板编程,十分强大

#include <stdio.h>

#define  MIN(type, x, y)  ({\
    type _x = x;\
    type _y = y;\
    _x > _y ? _y : _x;\
})
int Min(int x, int y)
{
    int _x = x;
    int _y = y;
    return _x > _y ? _y : _x;
}
int main(void)
{
    int i = 2;
    int j = 6;
    printf("min = %d\r\n", Min(i++, j++));
    printf("min = %.2f\r\n", MIN(float, 3.14, 3.15));
}

在VS中需要多传入参数做返回

#include <stdio.h>

#define  MIN(type, x, y,c)  {\
    type _x = x;\
    type _y = y;\
    c = _x > _y ? _y : _x;\
}
int Min(int x, int y)
{
    int _x = x;
    int _y = y;
    return _x > _y ? _y : _x;
}
int main(void)
{
    int i = 2;
    int j = 6;
    float c;
    printf("min = %d\r\n", Min(i++, j++));
    MIN(float, 3.14, 3.15, c)
    printf("min = %.2f\r\n", c);
}

函数作为形参,并调用

#include <stdio.h>

void add(void) 
{
	printf("hello\n");
}
void add_2(void (*ptr)(void)) 
{
	ptr();
}
int main(void) 
{
	add_2( add);
	return 0;
}

数组所在内存地址

数组地址加一详解_奋斗的大庆的博客-CSDN博客_数组地址加1

#include <stdio.h>

int main(void)
{
	int arr[2][3] = { {1,2,3},{4,5,6} };
	int i, j;
	printf("&arr:%d\t\n", &arr);
	printf("&arr+1:%d\t\n", &arr+1);	//把&arr+1这个地址打印
	printf("(int*)(&arr+1):%d\t\n", (int*)(&arr + 1));	//把&arr+1这个地址用一个指针指向
	for(i=0;i<2;i++)
		for(j=0;j<3;j++)
			printf("&arr[%d][%d]:%d\t\n",i,j,&arr[i][j]);
}

二重数组做形参,并通过指针操作

        二重数组相当于一个一维数组分了若干段,arr[0][0]指向第一行第一列

        代码分析:对于arr[2][3],

                                  0.以&arr,作为实参可以与(* a)[2][3]匹配

                                  1.以数组名arr,作为实参可以与a[][3]匹配,和(*a)[3]匹配,

                                                与&arr[0]等价

                                   2.以arr[0],作为实参可以与(*a)匹配,

                                                与&arr[0][0]等价

         结论:二维数组的地址等价于一个二维数组指针(*a)[2][3],&arr为其值(首地址)

                    二维数组等价于一个一维数组指针(*a)[3]&arr[0](首地址)为其值,等价于arr

                    二维数组等价于一个指针(*a)&arr[0][0](首地址)为它们的值,等价于arr[0]

                    二维数组为2x3的数值组合,&arr[0][0]~&arr[1][3]为它们的地址

#include<stdio.h>
#include <corecrt_malloc.h>

void print(int a[][3])
{
    int i, j;
    for (i = 0; i < 2; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    for (i = 0; i < 2; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", *a[i] + j);
        }
        printf("\n");
    }
    printf("\n");
}

void print_2(int (*p))
{
    int i, j;
    for (i = 0; i < 2; i++)
    {
        for (j = 0; j < 3; j++)
            printf("%d ", *(p + i * 3 + j));
        printf("\n");
    }
    printf("\n");
}
void print_3(int (*a)[3])
{
    int i, j;
    for (i = 0; i < 2; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", *a[i] + j);
        }
        printf("\n");
    }
    printf("\n");
}
void print_4(int(*a)[2][3])
{
    int  j;

     for (j = 0; j < 6; j++)
     {
        printf("%d ", *(*a[0]+j));
     }
        printf("\n");
    
}
void main(void)
{
    int i, j, arr[2][3] = {
      {1,2,3},
      {4,5,6}
    };
    print(arr);
    print_2(arr[0]);
    print_2(&arr[0][0]);
    print_3(arr);
    print_3(&arr[0]);
    print_4(&arr);
    printf("the a is %p\n", arr);
    printf("the a is %p\n", &arr);
}

三维指针及三重数组

#include <stdio.h>


void array_print(int a[][2][3]) //三维数组
{
    int i, j, k;
    for (i = 0; i < 2; i++) //相当于有两个一维指针
    {
        for (j = 0; j < 2; j++)
        {
            for (k = 0; k < 3; k++)
                //printf("%d", a[i][j][k]); //相当于有12个数字
                printf("%d", (*(a+i))[j][k]);
            printf("\n");
        }
        printf("\n");
    }
}

void array_print1(int* a[][3])  //一重二维数组指针
{
    int i, j;
    for (i = 0; i < 4; i++) //相当于有4个一维指针
    {
        for (j = 0; j < 3 ; j++)
            printf("%d", (a[i][j]));
        printf("\n");
    }
       
}
void array_print2(int** a[])    //二重一维数组指针
{
    int i;
    for(i=0;i<12;i++)   //12个一维指针指向12个数据
    printf("%d", a[i]); 
    printf("\n");
}
void array_print3(int*** a)     //三重指针
{
    int i, j;
    for (i = 0; i < 12; i++)    //相当于一个三重指针,一个指针
       // printf("%d", *(a + i));   //等价于 printf("%d", &**(a+i)); 
        printf("%d", a[i]);
}

int main(void)
{
    int a[2][2][3] = 
        { 
            {
                {1,2,3},
                {4,5,6}
            },
            {
                {7,8,9},
                {10,11,12}
            }
        };
    //int* ptr = (int*)(&a + 1);
    //printf("%d,%d",*(int *)(a+1),*(ptr-4));
    array_print(a);
    array_print1(a);
    array_print2(a);
    array_print3(a);
}

结构体数组及其指针

        3行3列指针,每一个行指针对应一个结构体,每一行中的每一列对应结构体中的一个成员

#include<stdio.h>
 
typedef struct test
{
    int a;
    int b;
    int c;
} TEST;
 
TEST arr[]={         //3行3列指针,每一个行指针对应一个结构体,每一行中的每一列对应结构体中的一个成员
    {1,2,3},
    {4,5,6},
    {7,8,9}
};
 
void main(void)
{
    TEST *tmp;
    tmp = arr;
 
    printf("tmp: %d, %d, %d,%d, %d, %d,%d, %d, %d\n", tmp[0].a, tmp[0].b, tmp[0].c, tmp[1].a, tmp[1].b, tmp[1].c, tmp[2].a, tmp[2].b, tmp[2].c);
    printf("arr: %d, %d, %d,%d, %d, %d,%d, %d, %d\n", arr[0].a, arr[0].b, arr[0].c, arr[1].a, arr[1].b, arr[1].c, arr[2].a, arr[2].b, arr[2].c);
}

 二重指针赋值

        #表示输出加0x,p1为i的地址,p2为p1的地址

#include<stdio.h>
int main(void)
{
    int i;
    int** p2 = NULL;
    int* p1 = NULL;

    p1 = &i;
    p2 = &p1;

    printf("p1 = %#x, p2 = %#x", p1, p2);   //#表示输出加0x.p1为i的地址,p2为p1的地址

    return 0;
}

结构体对其内部指针成员的引用

两种方法

#include <stdio.h>
struct Stu_Info
{
    const char* name; // 总线名字
};
int main()
{
    struct Stu_Info mystudent;
    mystudent.name = "bob";
    printf("%s\n",mystudent.name);

    struct Stu_Info mystudent1 = {
        .name = "bob",
    };
    printf("%s\n",mystudent1.name);
    return 0;
}

两个 !! : (383条消息) C语言中双感叹号(!!)的含义_!()c语言是啥_Qidi_Huang的博客-CSDN博客 

把非 0 值转换为 1,0 值为 0  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值