C语言你不得不知道的小知识

C语言你不得不知道的小知识:

1: 常见的变量修饰关键字:static、const、extern、volatile、register
static:(该变量保存在全局静态区) 
a.修饰局部变量——>会提升局部变量的生存周期(此时局部变量可以理解为全局变量)
b.修饰全局变量——>作用域被限制——>被限制到当前的原文件中 c.修饰函数——>作用域被限制——>被限制到当前的原文件中

const:(该变量保存在常量区)
1.声明常变量,,使得指定的变量不能被修改。
2.修饰函数形参,使得形参在函数内不能被修改,表示输入参数。
3.修饰函数返回值,使得函数的返回值不能被修改。

extern: 用于修饰变量或函数,表明该变量或函数都是在别的文件中定义的,提示编译器在其他文件中寻找定义。

volatile: 强制编译器每次从内存中取得该变量的值,而不是从被优化后的寄存器/缓存中读取。

register:(该变量保存在寄存器中)
用来声明为寄存器变量。也为局部变量,只在声明它的函数内有效。它是保存在寄存器之中的。速度要快很多。

2:  一个程序占用的内存通常分为以下几个部分:代码区、常量区、全局(静态)存储区、堆区、栈区
代码区:
存放程序编译后的二进制代码【代码】

常量区:
存放只读变量和字符串常量,一经初始化,不可修改.【const变量、字符串】

全局(静态)存储区:
全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,
未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。因此,又可以分为.data段和.bss段。

.data段 (数据段):
存放已初始化的全局和静态变量。在编译器编译的时候,会给已初始化的数据分配内存空间,数据保存在目标文件中。
.bss段 (bss段):
(bss是英文Block Started by Symbol的简称。)存放未初始化或初始化为0的全局和静态变量。在编译器编译的时候,不会给该段的数据分配空间,只是记录数据所需的空间大小。

堆区:
由程序员手动申请/释放,若不手动释放,程序结束后由系统回收.【malloc申请的内存,用完一定要free释放掉】   效率高, 向下压栈, 占用空间小


栈区:
由系统自动分配/释放,存放函数参数,局部变量等.【局部变量、函数参数、数组等】  自由度大,向上存放数据, 占用空间大 

3:
指针函数:一个函数,它的返回值是指针。
函数指针:一个指针,它指向一个函数。

【指针函数】定义形式:
    类型 *指针变量名 (参数列表): 
例如:
    int *p(int i, int j); 
说明:
    p是一个函数,该函数有2个整形参数,它的返回值是一个指针,指向一个整数类型。
    因为()的优先级比*更高,所以可以写成:int *(p(int i,int j)),
    表明它是一个函数,返回值是一个指向整型的指针。

【函数指针】定义形式:
    类型 (*指针变量名)(参数列表); 
例如:
    int (*p)(int i,int j); 
说明:
    p是一个指针,它指向一个函数,该函数有2个整形参数,返回类型为int。
    p首先和*结合,表明p是一个指针。然后再与()结合,
    表明它指向的是一个函数。指向函数的指针也称为函数指针。
    表明它是一个函数,返回值是一个指向整型的指针。

4:指针与const关键字
a)char * const p;
b)char const *p;
c)const char *p;
d) char const* const p;

分析:
a)一个指针,指向char数据类型,p是常量。【指针不可更改】
b)一个指针,指向char数据类型,p指向的数据是常量。【所指的内容不可更改】
c)一个指针,指向char数据类型,p指向的数据是常量。(char放在前后都没关系)
d)一个指针,指向char数据类型,p是常量,p指向的数据也是常量。【指针和所指向的数据都不可更改】

总结: const在*左边:内容不可改变
       const在*右边:指针不可改变

5: 指针与数据类型
问题:
a) 一个整型数(An integer) 
b)一个指向整型数的指针( A pointer to an integer) 
c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)r 
d)一个有10个整型数的数组( An array of 10 integers) 
e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers) 
f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers) 
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer) 
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )
i) 一个函数,该函数的参数是整数类型,该函数的返回值是指针。

答案:
a)int p;
b)int *p;
c)int **p;
d)int p[10];
e)int (*p[10]);
f)int (*p)[10];
g)int (*p)(int);
h)int (*p[10])(int);
i)int *p(int);


6:善用位运算,如下:
a=a%8; (前提是2的倍数)
可以改为:
a=a&7; (a=a&(8-1))
位操作只需一个指令周期即可完成(更贴近于代码语言),而大部分的C编译器的“%”运算均是调用子程序来完成,代码长、执行速度慢。
善用移位实现乘除法运算,如下:
a=a*4; (a * 2^2)
b=b/4;
可以改为:
a=a<<2; (左移)(a * 2^2)
b=b>>2; (右移)(a / 2^2)
通常如果需要乘以或除以2n,都可以用移位的方法代替。用移位的方法得到代码比调用乘除法子程序生成的代码效率高。实际上,只要是乘以或除以一个整数,均可以用移位的方法得到结果,如:
a=a9
可以改为:
a=(a<<3)+a  (a * 2 ^3)+ a

7:字符数组初始化与不初始化的区别

/*server.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define M 3
#define Y(n) ((M + 1)*n)

int main()
{
    int n = 3;
    int size = 0;
    char a[20];
    printf("a %d\n", strlen(a));
    for (int j = 0; j < 10; j++) {
        a[j] = '0';
    }
    printf("a %d\n", strlen(a));
    printf("a %s\n", a);


    char b[20] = {0}; // 等价于初始化为'\0'
    printf("b %d\n", strlen(b));
    for (int j = 0; j < 10; j++) {
        b[j] = '0';
    }
    printf("b %d\n", strlen(b));
    printf("b %s\n", b);

    int z = 2 * (M + Y(5 + 1)); // 2 * (3 + (3 + 1)* 5 + 1) = 48
    printf("z is %d", z);

    return 0;
}

8:回调函数

回调函数:就是一个通过函数指针调用的函数。

如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

函数指针也是一种指针,只是它指向的不是整型,字符型而是函数。函数指针就是通过指向这个函数的入口,从而调用这个函数。

函数指针定义:

void (*p_func)(int, int, float) = NULL;

函数指针的赋值:

p_func= func1 (或者 p_func = &func1)

使用数指针调用函数:

int res = p_func(1, 2, 3.0)

使用函数指针作为参数传给函数:

void func4(int a, int b, float c, void (*p_func)(int, int, float)){

     (*p_func)(a, b, c);

}

func4() {

    func3(1, 2, 3.0, func1);

}


四则运算的具体实例:

float  ADD(float a, float b) {

   return a + b;

}

float SUB(float a, flloat b) {

    return a - b;

}

float MUL(float a, float b) {

    return a * b;

}

flaot DIV(flaot a, float b) {

    flaot a / b;

}

typedef struct OP {

    float (*p_addfunc)(int, int, float)
    float (*p_subfunc)(int, int, float)
    float (*p_mulfunc)(int, int, float)
    float (*p_divfunc)(int, int, float)

} OP; 

void initOP(OP* op)
{
    
    op->p_addfunc = ADD;
    op->p_subfunc = SUB;
    op->p_mulfunc = &MUL;
    op->p_delfunc = &DIV;
}

float mul_opretion_func(float a, float b, (*p_func)(int, int)) {
    return (*p_func)(a, b);
}

int main()
{
   mul_opretion_func(1.0, 2.0, op->p_addfunc);
   mul_opretion_func(1.0, 2.0, op->p_subfunc);
   mul_opretion_func(1.0, 2.0, MUL);
   mul_opretion_func(1.0, 2.0, DIV);
    
}

9:C语言的库函数

常见的使用

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>


int main()
{
    int a = 221;
    char s[123] = {0};
    char* ss = (char*)malloc(123 * sizeof(char));
    sprintf(s, "%d", a);
    strcpy(ss, "aaa");
    strcat(s, "bbb");
    printf("%s\n", s);
    printf("%s\n", ss);
    int s_len = strlen(s);
    printf("s len is %d\n", s_len);
    char* sss = (char*)calloc(123, sizeof(char));
    memset(sss, 0, 123 * sizeof(char));
    printf("%s\n", sss);
    strcpy(sss, "aaavvvv");
    printf("%s\n", sss);
    return 1;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值