C语言基础知识

系列文章目录

第一章 C语言基础知识

第二章 C语言控制语句

第三章 C语言函数详解

第四章 C语言数组详解

第五章 C语言操作符详解

第六章 C语言指针详解

第七章 C语言结构体详解


目录

系列文章目录

目录

1. Hello word

2. 数据类型

3. 变量、常量

3.1 定义变量的方法

3.2 变量的命名

3.3 变量的分类

3.4 变量的作用域和生命周期

3.5 常量

4. 字符串和转义字符

4.1 字符串

4.2 转义字符

5. 选择语句

6. 循环语句

7. 函数

8. 数组

8.1 数组定义

8.2 数组的下标

8.3 数组的使用

9. 操作符

10. 关键字

11. 指针

11.1 内存

11.2 指针和指针变量

11.3 指针变量的大小

12. 结构体


1. Hello word

#include <stdio.h>
int main() //main函数是程序的入口,有且仅有一个
{
    printf("hello world\n");
    return 0;
}

2. 数据类型

char           字符型(数据长度:1)
short          短整型(2)
int              整形 (4)
long           长整型(4)
long long    更长的整形(8)
float            单精度浮点数(4)
double        双精度浮点数(8)

3. 变量、常量

3.1 定义变量的方法

int age = 10;
float weight = 5.5f;
char ch = 'a';

3.2 变量的命名

1. 只能由字母(包括大写和小写)、数字和下划线( _ )组成。
2. 不能以数字开头。
3. 长度不能超过63个字符。
4. 变量名中区分大小写的。
5. 变量名不能使用关键字。

3.3 变量的分类

  局部变量和全局变量
  当局部变量和全局变量同名的时候,局部变量优先使用。
#include <stdio.h>
int year = 2019;//全局变量
int main()
{
    int now = 2018;//局部变量
    printf("now = %d\n", now);
    printf("year = %d\n", year);
    return 0;
}

3.4 变量的作用域和生命周期

  • 作用域
作用域(scope)是程序设计概念,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
1. 局部变量的作用域是变量所在的局部范围。
2. 全局变量的作用域是整个工程。
  • 生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
2. 全局变量的生命周期是:整个程序的生命周期。

3.5 常量

  • 常量分为以下以下几种:
字面常量
const 修饰的常变量
#define 定义的标识符常量
枚举常量
//例子上的 test 为 const 修饰的常变量, const修饰的常变量在C语言中只是在语法层面限制了变量 test 不能直接被改变
//但是 test 本质上还是一个变量的,所以叫常变量。
#include <stdio.h>
enum Gender // 这是一个枚举类型定义。枚举类型Gender有三个成员:MALE、FEMALE和SECRET。
{
 MALE,
 FEMALE,
 SECRET
};
//枚举常量默认从0开始编号,即MALE为0,FEMALE为1,SECRET为2。

int main()
{
    //这些字面常量在这里没有实际作用,仅作为展示。
    5;//字面常量
    5.5;//字面常量
    
    //这里定义了一个const修饰的常变量test,其值被初始化为123。
    //由于它被const修饰,尝试修改test的值(如test = 5.14;)将导致编译错误,因为const变量的值不可修改。
    const float test = 123;   //这里的pai是const修饰的常变量
    test = 5.14;//不能直接修改常变量的值,否则会报错
    
    //#define的标识符常量是在预处理阶段由预处理器处理的,它是在编译阶段被替换的,不占内存。
    #define T 100
    printf("t = %d\n", T);
    
    //枚举常量演示
    printf("%d\n", MALE);
    printf("%d\n", FEMALE);
    printf("%d\n", SECRET);
    //打印前面定义的枚举常量的值。根据枚举的默认行为,输出将依次是0, 1, 和2。
    return 0;
}

4. 字符串和转义字符

4.1 字符串

"hello world.\n"
这种由双引号( Double Quote )引用的一串字符称为字符串字面值( String Literal), 或者简称字符串。 字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串本身的内容。
int main()
{
    char arr1[] = "bit";
    char arr2[] = {'b', 'i', 't'};
    char arr3[] = {'b', 'i', 't', '\0'};
    printf("%s\n", arr1);
    printf("%s\n", arr2);
    printf("%s\n", arr3);
    return 0;
}

从输出结果可以看出\0 结束标志的作用。

4.2 转义字符

\?     防止连续的问号被解析成三字母词(Trigraphs)。三字母词是C语言的一种特性,用于表示那些在某些键盘上无法直接输入的字符。例如,??=表示#
\'       用于在字符常量中表示单引号。因为单引号用于界定字符常量,所以需要用转义字符来表示单引号本身。例如, '\'' 表示单引号字符。
\“      用于在字符串中表示双引号。双引号用来定义字符串,所以在字符串内部表示双引号本身时需要用到这个转义字符。例如, "he said, \"hello\"'
\\      用于表示反斜杠自身。反斜杠用作引入转义字符,因此当需要在字符串或字符常量中直接包含一个反斜杠时,必须使用 \\
\a      警告字符(通常会触发系统的响铃或其它警告信号)。
\b      退格符,使光标回退一格或删除一个前面的字符。
\f       进纸符,用于打印机控制,使打印机将纸张向前推进到下一页的顶部。
\n      换行符,用于结束当前行并将光标移动到下一行的开始。
\r       回车符,将光标移回当前行的开头。
\t       水平制表符(Tab),在文本中插入一个水平制表位,常用于文本的对齐。
\v      垂直制表符,使光标上移一行,但保持在当前列。
\ddd   d d d表示 1~3位 八进制的数字。 如: \130 表示八进制数130对应的ASCII字符 X
\xdd   d d表示 2位 十六进制数字。 如: \x30 表示十六进制30对应的ASCII字符 0
#include <stdio.h>
int main()
{
    printf("%c\n", '\''); //在屏幕上打印一个单引号
    printf("%s\n", "\""); //在屏幕上打印一个双引号
    printf("%d\n", strlen("abcdef"));
    // \62被解析成一个转义字符
    printf("%d\n", strlen("c:\test\628\test.c")); //在屏幕上打印一个目录
    return 0;
}

5. 选择语句

#include <stdio.h>
int main()
{
    int select = 0;
    // 提示用户输入选择,1代表学习C语言,0代表学习Python
    printf("学习C还是python(选择1 or 0):>");
    // 使用scanf函数读取用户输入的整数,并将其存储在select变量中
    scanf("%d", &select);
    if(select == 1)
   {
       printf("学习C语言\n");
   }
    else
   {
       printf("学习Python\n");
   }
    return 0;
}

6. 循环语句

C语言一共有三种循环:

while语句
for语句
do ... while语句
//while循环的实例
#include <stdio.h>
int main()
{
    printf("循环开始\n");
    int line = 0; // 定义整型变量line并初始化为0,用于控制循环的次数
    while(line<=10) // // while循环的条件是line小于或等于10
   {
        line++; // 在循环体的开始先将line的值加1
        printf("正在循环\n");
   }
    if(line>10) // 当line的值大于10时,while循环结束
        printf("循环结束\n");
     return 0;
}

7. 函数

函数是一组组织在一起以执行特定任务的语句块。函数可以执行计算、执行操作、处理数据等,并且可以重复使用。

首先看下面这段代码(常规代码实现加法)

#include <stdio.h>
int main()
{
    int num1 = 0;
    int num2 = 0;
    int sum = 0;
    printf("输入两个数值:>");
    scanf("%d %d", &num1, &num2);
    sum = num1 + num2;
    printf("sum = %d\n", sum);
    return 0;
}

下面改成通过加法函数的方式来实现。

#include <stdio.h>
int Add(int x, int y) // 定义一个函数Add,接收两个参数x和y
{
   int z = x+y; // 在函数内部计算x和y的和,并将结果存储在变量z中
   return z; // 返回计算得到的和
}
int main()
{
    int num1 = 0;
    int num2 = 0;
    int sum = 0;
    printf("输入两个数值:>");
    scanf("%d %d", &num1, &num2);
    sum = Add(num1, num2); // 调用函数Add,传入num1和num2作为参数,并将返回值赋给sum
    printf("sum = %d\n", sum);
    return 0;
}

8. 数组

8.1 数组定义

int arrays[10] = {1,2,3,4,5,6,7,8,9,10}; //定义一个整形数组,最多放10个元素

8.2 数组的下标

在C语言中,数组的每个元素都有一个下标,数组的下标是一个索引,用来访问数组中的元素。数组下标从0开始编号,因此一个有N个元素的数组的下标范围是从0到N-1。
int arrays[10] = {0}; //如果数组10个元素,下标的范围是0-9

这里 arrays是数组的名称,[10] 指定了数组的大小,意味着它可以包含10个整数元素。数组被初始化为 {0},这表示数组中的所有元素都被初始化为0。

数组的每个元素都可以通过其下标来访问。数组 arrays的下标和对应元素的值如下所示:

  • arrays [0] 的值是 0(第一个元素)
  • arrays [1] 的值是 0(第二个元素)
  • arrays [2] 的值是 0(第三个元素)
  • ...
  • arrays [9] 的值是 0(第十个元素)

8.3 数组的使用

#include <stdio.h>
int main()
{
 int i = 0;
 // 声明并初始化一个名为arrays的整数数组,包含10个整数元素,元素值从1到10
 int arrays[10] = {1,2,3,4,5,6,7,8,9,10};
 // for循环开始,初始条件为i=0,循环继续的条件是i<10,每次循环结束后i的值增加1
 for(i=0; i<10; i++)
 {
    printf("%d", arrays[i]); // 使用printf函数打印当前i所指向的数组元素的值
 }
    printf("\n");
    return 0;
}

9. 操作符

在编程中,操作符是用来在表达式中执行特定操作的符号。C语言提供了多种操作符。
算术操作符
  1. +:加法操作符,用于计算两个数的和。
  2. -:减法操作符,用于计算两个数的差。
  3. *:乘法操作符,用于计算两个数的积。
  4. /:除法操作符,用于计算两个数的商。
  5. %:求余操作符(模运算符),用于计算两个数相除的余数。
移位操作符
  1. >>:右移操作符,将数字的位向右移动指定的位数,高位丢弃,低位通常补0。
  2. <<:左移操作符,将数字的位向左移动指定的位数,低位补0。
位操作符
  1. &:按位与操作符,对两个数的二进制表示进行逐位与操作。
  2. ^:按位异或操作符,对两个数的二进制表示进行逐位异或操作。
  3. |:按位或操作符,对两个数的二进制表示进行逐位或操作。
赋值操作符
  1. =:基本赋值操作符,将右侧表达式的值赋给左侧的变量。
  2. +=:加法赋值操作符,将右侧表达式的值加上左侧变量的值,然后将结果赋给左侧变量。
  3. -=:减法赋值操作符,从左侧变量的值中减去右侧表达式的值,然后将结果赋给左侧变量。
  4. *=:乘法赋值操作符,将左侧变量的值与右侧表达式的值相乘,然后将结果赋给左侧变量。
  5. /=:除法赋值操作符,将左侧变量的值除以右侧表达式的值,然后将结果赋给左侧变量。
  6. &=:按位与赋值操作符,对左侧变量与右侧表达式进行按位与操作,然后将结果赋给左侧变量。
  7. ^=:按位异或赋值操作符,对左侧变量与右侧表达式进行按位异或操作,然后将结果赋给左侧变量。
  8. |=:按位或赋值操作符,对左侧变量与右侧表达式进行按位或操作,然后将结果赋给左侧变量。
  9. >>=:右移赋值操作符,将左侧变量右移右侧表达式指定的位数,然后将结果赋给左侧变量。
  10. <<=:左移赋值操作符,将左侧变量左移右侧表达式指定的位数,然后将结果赋给左侧变量。
单目操作符
  1. !:逻辑非操作符,用于取反布尔表达式的真值。如果操作数为真(非0),结果为假(0);如果操作数为假(0),结果为真(非0)。
  2. -:一元负号,用于返回操作数的负值。
  3. +:一元正号,通常省略不写,表示操作数的正值。
  4. &:取地址操作符,返回变量的内存地址。
  5. sizeof:返回操作数的类型长度,单位是字节。
  6. ~:按位取反操作符,对整数的二进制表示进行按位取反。
  7. --:递减操作符,可以作为前缀(先减少,再返回值)或后缀(先返回值,再减少)。
  8. ++:递增操作符,同样可以作为前缀或后缀。
  9. *:间接访问操作符或解引用操作符,用于访问指针指向的变量。
  10. (类型):强制类型转换,用于将表达式的类型转换为括号中指定的类型。
关系操作符
  1. >:大于操作符,如果左侧操作数大于右侧操作数,则返回真(非0)。
  2. >=:大于或等于操作符,如果左侧操作数大于或等于右侧操作数,则返回真(非0)。
  3. <:小于操作符,如果左侧操作数小于右侧操作数,则返回真(非0)。
  4. <=:小于或等于操作符,如果左侧操作数小于或等于右侧操作数,则返回真(非0)。
  5. !=:不等于操作符,如果两个操作数不相等,则返回真(非0)。
  6. ==:等于操作符,如果两个操作数相等,则返回真(非0)。
逻辑操作符
  1. &&:逻辑与操作符,当所有操作数都为真时,结果为真;否则为假。
  2. ||:逻辑或操作符,如果任一操作数为真,则结果为真;如果所有操作数都为假,结果为假。
条件操作符
  1. exp1 ? exp2 : exp3 三元条件操作符,如果表达式exp1 为真(非0),则返回exp2的值,否则返回exp3的值。
逗号表达式
  1. exp1, exp2, exp3, …expN  逗号操作符用于链接表达式,从左到右顺序求值,并返回最后一个表达式的值。
下标引用、函数调用和结构成员
  1. []:下标操作符,用于访问数组中的元素。
  2. ():函数调用操作符,用于调用函数。
  3. .:直接成员访问操作符,用于访问结构体或联合体的成员。
  4. ->:间接成员访问操作符,用于通过指向结构体或联合体的指针来访问其成员。

10. 关键字

C语言关键字是预先定义的保留字,它们具有特定的意义,用来表示数据类型、流程控制语句和其他编程结构。关键字不能用作变量名、函数名或其他标识符名称。

auto  break   case  char  const   continue  default  do   double else  enum   
extern float  for   goto  if   int   long  register    return   short  signed
sizeof   static struct  switch  typedef union  unsigned   void  volatile  while
  1. auto:用于声明自动变量,其存储类别指定为自动存储期。
  2. break:用于立即退出最近的循环或 switch 语句。
  3. case:与 switch 语句结合使用,用于指定一个条件分支。
  4. char:用于声明字符型变量或数组。
  5. const:用于声明一个常量,表示变量的值在程序运行时不会被修改。
  6. continue:使控制流跳过当前循环的剩余部分,立即进入下一次循环的迭代。
  7. default:与 switch 语句结合使用,定义一个默认分支,当没有匹配的 case 时执行。
  8. do:与 while 一起使用,创建一个循环结构,至少执行一次循环体。
  9. double:用于声明双精度浮点型变量或数组。
  10. else:与 if 语句结合使用,用于创建条件分支。
  11. enum:定义一个枚举类型,用于声明一组命名的整型常量。
  12. extern:声明一个变量或函数是在别处定义的,即指示编译器寻找另一个文件中的定义。
  13. float:用于声明单精度浮点型变量或数组。
  14. for:创建一个循环结构,可以指定初始化、条件和迭代表达式。
  15. goto:用于无条件地跳转到程序中标记的位置。
  16. if:用于创建基于条件的分支。
  17. int:用于声明整型变量或数组。
  18. long:用于声明长整型变量或数组,也可以用来声明长双精度类型 long double
  19. register:提示编译器尝试使用寄存器来存储变量,以便快速访问。
  20. return:从函数返回一个值并结束函数的执行。
  21. short:用于声明短整型变量或数组。
  22. signed:与整型数据类型结合使用,指明变量可以存储负数。
  23. sizeof:计算类型或变量所占内存大小的运算符。
  24. static:声明静态变量或函数,使其在文件内保持局部作用域。
  25. struct:定义一个结构体类型,用于将不同类型的数据项组合成一个单元。
  26. switch:根据一个整型表达式的值选择多个代码块之一来执行。
  27. typedef:为一个已存在的类型创建一个新的名称(别名)。
  28. union:定义一个联合体,其成员共享同一块内存。
  29. unsigned:与整型数据类型结合使用,指明变量只能存储非负数。
  30. void:表示无类型,用于指定没有返回值的函数或未指定类型的指针。
  31. volatile:指示编译器一个变量的值可能以编译器未预料的方式改变。
  32. while:创建一个循环结构,在满足指定条件的情况下反复执行循环体。

11. 指针

11.1 内存

       计算机中程序的运行都是在内存中进行的 。 为了有效的使用内存,将内存划分成小的内存单元,每个内存单元的大小是1个字节。每个存储位置都有一个独一无二的内存地址,通常表示为十六进制数。在现代计算机系统中,这些地址是数字的形式,用来定位内存中的每个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
在程序的编写中会用到各种变量, 变量也是创建在内存中的,每个内存单元都有地址,所以变量也是有地址的。
取出变量地址的代码示例:
#include <stdio.h>

int main()
{
    int num = 10;  // 声明一个类型为int的变量num,并初始化为10。
    &num;  // 取出变量num的地址。
    // 使用printf函数打印num的地址。%p格式说明符用于打印指针或地址。
    // 在打印时,地址通常以十六进制形式表示。
    printf("%p\n", &num);
    return 0;
}

11.2 指针和指针变量

在C语言中,指针是一个非常强大的特性,因为它允许程序直接访问和操作内存。指针本身是一个变量,但它存储的不是普通的数据,而是另一个变量的地址。

如果想储存地址,需要定义指针变量。
#include <stdio.h>
int main()
{
 int num = 10; // 定义一个整型变量num,并初始化为10。
 int *p = &num; // 定义一个整型指针变量p,并初始化为num的地址。
 *p = 20; // 通过指针p修改num的值。现在num的值变成了20。
 return 0;
}
#include <stdio.h>

int main()
{
    char word = 'w';  // 声明一个类型为char的变量word,并初始化为字符'w'
    char* pc = &word;  // 声明一个类型为char*的指针变量pc,并初始化为变量word的地址
    *pc = 'q';  // 解引用指针pc,即访问pc指向的地址(即word的地址)并将其值修改为'q'

    printf("%c\n", word);  // 这里会打印出'q'
    return 0; 
}

这里可能会感觉程序本来可以直接修改num的值,现在反而多用了一个指针来修改,好像更复杂了。然而,指针的力量在于它们提供了访问和操作内存的灵活性,这在以下几个场景中非常有用:

  1. 函数参数传递:如果你想在函数中修改变量的值,并且让这些修改反映到调用者那里,你需要使用指针。在C语言中,函数参数是通过值传递的,这意味着函数接收的是参数值的副本。通过传递指向实际变量的指针,函数可以直接修改变量的值。

  2. 动态内存分配:C语言使用指针来动态分配和管理内存。通过指针,你可以在运行时分配内存块,其大小并不需要在编译时确定,这为创建复杂的数据结构如链表、树、图等提供了可能。

  3. 数组和字符串操作:指针在处理数组和字符串时非常有用。字符串在C中通过字符数组实现,指针可以方便地遍历和操作这些数组。

  4. 效率:对于大型数据结构,如大数组或结构体,使用指针传递它们的地址比复制整个数据结构要高效得多,因为只需要复制地址值而不是结构的每个部分。

  5. 接口和抽象:在一些情况下,指针用于创建对数据的抽象表示,比如文件句柄等。

  6. 底层操作:指针使得程序能够与硬件直接交互,这在嵌入式系统和操作系统的开发中尤为重要。

11.3 指针变量的大小

  • 在32位系统中,所有类型的指针的大小通常是4个字节(32位)。
  • 在64位系统中,所有类型的指针的大小通常是8个字节(64位)。

12. 结构体

结构体是一种用户自定义的数据类型,它允许存储不同数据类型的数据项。

比如描述一个人的信息,包含: 名字 + 年龄 + 性别 这几项信息。
struct people
{
    char name[20]; // 一个20个字符的数组,用于存储姓名
    int age;       // 一个 int 类型的变量,用于存储年龄
    char sex[5];   // 一个5个字符的数组,用于存储性别
};

结构体初始化和成员访问:

// 创建并初始化一个名为 s 的 people 结构体的实例,初始化时,每个值依次赋给结构体的成员
struct people s = {"某某某", 20, "男"};
// 使用结构体成员访问和打印
printf("name = %s age = %d sex = %s", s.name, s.age, s.sex);

指针访问结构体:

// 指针变量
struct people *ps = &s; //声明了一个指向 people 结构体的指针 ps,并将它初始化为 s 的地址
// 通过使用箭头操作符 ->,可以通过指针访问结构体的成员。
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps->id);

这两段代码示例展示了如何在C语言中使用结构体(struct),包括如何初始化结构体变量,如何直接访问结构体的成员,以及如何通过指针访问结构体的成员。

  • 29
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TENET-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值