八股-C语言

发布时间 2023-06-25 22:52:37作者: wxk1213

define和const关键字定义常量方式的异同

关于定义常量,"define"和"const"是两种不同的方式,它们有以下异同点:

  1. 定义方式:

    • "define"是C语言中使用的预处理指令,使用宏定义来创建常量。例如:#define PI 3.14159
    • "const"是C语言中的关键字,在编译时进行符号绑定来创建常量。例如:const double PI = 3.14159;
  2. 编译时机:

    • "define"是在预处理阶段进行文本替换,没有类型检查。它是简单的文本替换,不会分配内存。
    • "const"是在编译时进行符号绑定,并且具有类型检查。它会分配内存,并且在程序运行时具有地址。
  3. 范围和可见性:

    • "define"是全局替换,没有作用域限制。定义的常量在整个源代码中都可见。
    • "const"可以在特定的作用域内定义常量,如函数内部或者局部作用域内,具有作用域限制。
  4. 类型安全:

    • "define"不进行类型检查,只是简单的文本替换。因此,它可能导致一些意外的错误。
    • "const"是类型安全的,编译器会对其进行类型检查,确保赋值和使用的一致性

综上所述,"define"是一种简单的文本替换方式来定义常量,而"const"是在编译时进行符号绑定的关键字,具有类型检查和作用域限制。使用"const"方式更安全,因为它提供了类型检查和更好的可读性,而"define"则更加灵活但容易出现潜在的错误。

 

 

register存储类:用于定义存储在寄存器中而不是 RAM 中的局部变量。所以变量的访问速度更快,但是它不能直接取地址。

例如:

register int miles;

 

static 存储类:指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。

static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。

例如:

#include <stdio.h>
 
/* 函数声明 */
void func1(void);
 
static int count=10;        /* 全局变量 - static 是默认的 */
 
int main()
{
  while (count--) {
      func1();
  }
  return 0;
}
 
void func1(void)
{              
  static int thingy=5;
  thingy++;
  printf(" thingy 为 %d , count 为 %d\n", thingy, count);
}

实例中 count 作为全局变量只能在该文件下的函数内使用,thingy 使用 static 修饰后,不会在每次调用时重置。

输出结果:

thingy 为 6 , count 为 9

thingy 为 7 , count 为 8

。。。

  

extern存储类:定义在其他文件中声明的全局变量或函数。当使用 extern 关键字时,不会为变量分配任何存储空间,而只是指示编译器该变量在其他文件中定义。

 

每个C程序都至少有一个函数,即主函数 main()。

函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实际主体。

一般形式:

return_type function_name( parameter list ){
    body of the function
}

 返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。

 函数名称:function_name这是函数的实际名称。

 参数:parameter参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。

 函数主体:函数主体body of the function包含一组定义函数执行任务的语句。

 

 

作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问。C 语言中有三个地方可以声明变量:

1、在函数或块内部的局部变量

2、在所有函数外部的全局变量

3、在形式参数的函数参数定义中

因为函数的参数,形式参数,被当作该函数内的局部变量,如果与全局变量同名它们会优先使用。

 

全局变量与局部变量在内存中的区别:

 全局变量保存在内存的全局存储区中,占用静态的存储单元;

 局部变量保存在栈中,只有在所在函数被调用时才动态地为变量分配存储单元。

 

 

函数指针是指向函数的指针变量。

例子:

#include <stdio.h>
 
int max(int x, int y)
{
    return x > y ? x : y;
}
 
int main(void)
{
    /* p 是函数指针 */
    int (* p)(int, int) = & max; // &可以省略
    int a, b, c, d;
 
    printf("请输入三个数字:");
    scanf("%d %d %d", & a, & b, & c);
 
    /* 与直接调用函数等价,d = max(max(a, b), c) */
    d = p(p(a, b), c); 
 
    printf("最大的数字是: %d\n", d);
 
    return 0;
}

 

回调函数

函数指针作为某个函数的参数

例子:

#include <stdlib.h>  
#include <stdio.h>
 
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    for (size_t i=0; i<arraySize; i++)
        array[i] = getNextValue();
}
 
// 获取随机值
int getNextRandomValue(void)
{
    return rand();
}
 
int main(void)
{
    int myarray[10];
    /* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/
    populate_array(myarray, 10, getNextRandomValue);
    for(int i = 0; i < 10; i++) {
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}

populate_array() 函数定义了三个参数,其中第三个参数是函数的指针。

回调函数 getNextRandomValue(),它返回一个随机值,它作为一个函数指针传递给 populate_array() 函数。

 

strcpy(s1, s2); 复制字符串 s2 到字符串 s1。

strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾。

strlen(s1); 返回字符串 s1 的长度。

strcmp(s1, s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。

strchr(s1, ch); 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。

strstr(s1, s2); 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。