我的C语言学习笔记

内容背景与简介

简介:C 语言是为了编写 UNIX 操作系统而被发明的,C 语言最开始是于 1972 年,由丹尼斯·里奇在贝尔电话实验室设在 DEC PDP-11 计算机上被首次实现。
C 语言标准是于 1988 年由美国国家标准协会(ANSI,全称 American National Standard Institute)制定的。

C语言的特点:

 -易于学习。
 - 结构化语言。
 - 它产生高效率的程序。
 - 它可以处理底层的活动。
 - 它可以在多种计算机平台上编译。

C11标准:(也被称为C1X)指ISO标准ISO/IEC 9899:2011,是当前最新的C语言标准。在它之前的C语言标准为C99。
新特性:

对齐处理(Alignment)的标准化(包括_Alignas标志符,alignof运算符,aligned_alloc函数以及<stdalign.h>头文件)。
_Noreturn 函数标记,类似于 gcc 的 __attribute__((noreturn))。
_Generic 关键字。
多线程(Multithreading)支持,包括:
_Thread_local存储类型标识符,<threads.h>头文件,里面包含了线程的创建和管理函数。
_Atomic类型修饰符和<stdatomic.h>头文件。
增强的Unicode的支持。基于C Unicode技术报告ISO/IEC TR 19769:2004,增强了对Unicode的支持。包括为UTF-16/UTF-32编码增加了char16_t和char32_t数据类型,提供了包含unicode字符串转换函数的头文件<uchar.h>。
删除了 gets() 函数,使用一个新的更安全的函数gets_s()替代。
增加了边界检查函数接口,定义了新的安全的函数,例如 fopen_s(),strcat_s() 等等。
增加了更多浮点处理宏(宏)。
匿名结构体/联合体支持。这个在gcc早已存在,C11将其引入标准。
静态断言(Static assertions),_Static_assert(),在解释 #if 和 #error 之后被处理。
新的 fopen() 模式,("…x")。类似 POSIX 中的 O_CREAT|O_EXCL,在文件锁中比较常用。
新增 quick_exit() 函数作为第三种终止程序的方式。当 exit()失败时可以做最少的清理工作。     

1、由实例入手(解释C语言头文件、主函数、注释、printf()等内容)

#include <stdio.h>					//	stdio.h 是一个头文件 (标准输入输出头文件) , #include 是一个预处理命令,用来引入头文件。 当编译器遇到 printf() 函数时,如果没有找到 stdio.h 头文件,会发生编译错误。
int main()						    //	 所有的 C 语言程序都需要有main() 函数,代码从 main() 函数开始执行。
{									//  函数执行起始位置
    /* 我的第一个 C 程序 */			//  这是单行注释	/*这是多行注释 */
    printf("Hello, World! \n");		//	printf() 用于格式化输出到屏幕。printf() 函数在 "stdio.h" 头文件中声明。
    return 0;						//	return 0; 语句用于表示退出程序。
    }								//	函数之行结束位

2、编译 & 执行 C 程序

Linux系统:
gcc hello.c,输入回车,编译代码。

1、单个文件
$ gcc hello.c
$ ./a.out
Hello, World!
2、多个 c 代码的源码文件
$ gcc test1.c test2.c -o main.out
$ ./main.out

2.1基本语法:

  • 分号";"
(英文的分号;) 在 C 程序中,分号是语句结束符,每个语句必须以分号结束。  
  • 注释:

“//单行"和”/* 多行*/"

//单行注释
/* 单行注释 */
单行或多行
/* 
 多行注释
 多行注释
 */
  • 标识符
C 标识符是用来标识变量、函数,或任何其他用户自定义项目的名称。一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9)。
C 标识符内不允许出现标点字符,比如 @、$ 和 %。C 是区分大小写的编程语言。因此,在 C 中,Manpower 和 manpower 是两个不同的标识符。下面列出几个有效的标识符:
  • 关键字
    关键字参数
  • C 中的空格
在 C 中,空格用于描述空白符、制表符、换行符和注释。空格分隔语句的各个部分,让编译器能识别语句中的某个元素(比如 int)在哪里结束,
  • C 数据类型
	|基本类型:| 它们是算术类型,包括两种类型:整数类型和浮点类型。|
	|枚举类型:|它们也是算术类型,被用来定义在程序中只能赋予其一定的离散整数值的变量|
	|void类型:|类型说明符 void 表明没有可用的值。 |
	|派生类型:|它们包括:指针类型、数组类型、结构类型、共用体类型和函数类型。|
  • 整数类型
    得到某个类型或某个变量在特定平台上的准确大小,可以使用 sizeof 运算符。
#include <stdio.h>
#include <limits.h>
int main()
{
   printf("int 存储大小 : %lu \n", sizeof(int)); 
   return 0;
}
类型存储大小值范围
char1 字节 -128 到127 或 0 到 255
unsigned char1 字节0 到 255
signed char1 字节-128 到 127
int2 或 4 字节-32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
unsigned int2 或 4 字节0 到 65,535 或 0 到 4,294,967,295
short2 字节-32,768 到 32,767
unsigned short2 字节0 到 65,535
long4 字节-2,147,483,648 到 2,147,483,647
unsigned long4 字节 0 到4,294,967,295
  • 浮点类型
类型存储大小值范围精度
float4 字节1.2E-38 到 3.4E+386 位小数
double8 字节2.3E-308 到 1.7E+30815 位小数
long double16 字节3.4E-4932 到 1.1E+493219 位小数
  • void 类型
序号类型与描述
函数返回为空C 中有各种函数都不返回值,或者您可以说它们返回空。不返回值的函数的返回类型为空。例如 void exit (int status);
函数参数为空C 中有各种函数不接受任何参数。不带参数的函数可以接受一个 void。例如 int rand(void)
指针指向 void类型为 void * 的指针代表对象的地址,而不是类型。例如,内存分配函数 void *malloc( size_t size ); 返回指向 void 的指针,可以转换为任何数据类型。

2.2、C 数据类型

  • 2.2.1 C 变量
    基本的变量类型: char 、int 、float 、double 、void 、枚举、指针、数组、结构、共用体等等

  • C 中的变量定义
    变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储。变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表,如下所示:

    type variable_list;
    int    i, j, k;
    char   c, ch;
    float  f, salary;
    double d;
    

    变量可以在声明的时候被初始化(指定一个初始值)

    type variable_name = value;
    extern int d = 3, f = 5;    // d 和 f 的声明与初始化
    int d = 3, f = 5;           // 定义并初始化 d 和 f
    byte z = 22;                // 定义并初始化 z
    char x = 'x';               // 变量 x 的值为 'x'
    
  • C 中的变量声明

    1、变量声明向编译器保证变量以指定的类型和名称存在,这样编译器在不需要知道变量完整细节的情况下也能继续进一步的编译。变量声明只在编译时有它的意义,在程序连接时编译器需要实际的变量声明。
    变量的声明有两种情况:

    1、一种是需要建立存储空间的。例如:int a 在声明的时候就已经建立了存储空间。
    2、另一种是不需要建立存储空间的,通过使用extern关键字声明变量名而不定义它。 例如:extern int a 其中变量 a 可以在别的文件中定义的。
    除非有extern关键字,否则都是变量的定义。
    extern int i; //声明,不是定义
    int i; //声明,也是定义
    

    如果需要在一个源文件中引用另外一个源文件中定义的变量,我们只需在引用的文件中将变量加上 extern 关键字的声明即可。
    `

  • 2.2.2 C 常量
    说明:常量是固定值,在程序执行期间不会改变

    整数常量:
    整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。(整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。)

    浮点常量:
    浮点常量由整数部分、小数点、小数部分和指数部分组成。
    当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的。

    字符常量

    字符常量是括在单引号中,例如,‘x’ 可以存储在 char 类型的简单变量中。

    在 C 中,有一些特定的字符,当它们前面有反斜杠时,它们就具有特殊的含义,被用来表示如换行符(\n)或制表符(\t)等。下表列出了一些这样的转义序列码:

    义序列含义
    \\ 字符
    ’ 字符
    "" 字符
    ?? 字符
    a警报铃声
    b退格键
    f换页符
    n换行符
    r回车
    t水平制表符
    v垂直制表符
    \ooo\一到三位的八进制数
    xhh . . .一个或多个数字的十六进制数

字符串常量

字符串字面值或常量是括在双引号 "" 中的。一个字符串包含类似于字符常量的字符:普通的字符、转义序列和通用的字符。

定义常量

在 C 中,有两种简单的定义常量的方式:

使用 #define 预处理器。
使用 const 关键字。

#define 预处理器
下面是使用 #define 预处理器定义常量的形式:

#define identifier value
#include <stdio.h>
#define LENGTH 10   
#define WIDTH  5
#define NEWLINE '\n'
int main()
{
   int area;  
   area = LENGTH * WIDTH;
   printf("value of area : %d", area);
   printf("%c", NEWLINE);
   return 0;
}

const 关键字
您可以使用 const 前缀声明指定类型的常量,如下所示:

const type variable = value;
#include <stdio.h>
int main()
{
   const int  LENGTH = 10;
   const int  WIDTH  = 5;
   const char NEWLINE = '\n';
   int area;  
   area = LENGTH * WIDTH;
   printf("value of area : %d", area);
   printf("%c", NEWLINE);
   return 0;
}

3、C 存储类

auto 存储类
auto 存储类是所有局部变量默认的存储类。

int mount;
auto int month;
上面的实例定义了两个带有相同存储类的变量,auto 只能用在函数内,即 auto 只能修饰局部变量。

register 存储类
register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 ‘&’ 运算符(因为它没有内存位置)。

register int  miles;
寄存器只用于需要快速访问的变量,比如计数器。还应注意的是,定义 'register' 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制。

static 存储类
static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。
static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。
全局声明的一个 static 变量或方法可以被任何函数或方法调用,只要这些方法出现在跟 static 变量或方法同一个文件中。

以下实例演示了 static 修饰全局变量和局部变量的应用:
实例

#include <stdio.h>
/* 函数声明 */
void func1(void);
static int count=10;        /* 全局变量 - static 是默认的 */
int main()
{
  while (count--) {
      func1();
  }
  return 0;
}
void func1(void)
{
/* 'thingy' 是 'func1' 的局部变量 - 只初始化一次
 * 每次调用函数 'func1' 'thingy' 值不会被重置。
 */                
  static int thingy=5;
  thingy++;
  printf(" thingy 为 %d , count 为 %d\n", thingy, count);
}

实例中 count 作为全局变量可以在函数内使用,thingy 使用 static 修饰后,不会在每次调用时重置。
可能您现在还无法理解这个实例,因为我已经使用了函数和全局变量,这两个概念目前为止还没进行讲解。即使您现在不能完全理解,也没有关系,后续的章节我们会详细讲解。当上面的代码被编译和执行时,它会产生下列结果:
extern 存储类
extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当您使用 extern 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。
当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。
extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候,如下所示:
第一个文件:main.c
实例

#include <stdio.h>
int count ;
extern void write_extern(); 
int main()
{
   count = 5;
   write_extern();
}

第二个文件:support.c
实例

#include <stdio.h>
extern int count; 
void write_extern(void)
{
   printf("count is %d\n", count);
}

在这里,第二个文件中的 extern 关键字用于声明已经在第一个文件 main.c 中定义的 count。现在 ,编译这两个文件,如下所示:

$ gcc main.c support.c

这会产生 a.out 可执行程序,当程序被执行时,它会产生下列结果:

count is 5

4、C 运算符

算术运算符

运算符描述实例
+把两个操作数相加A + B 将得到 30
-从第一个操作数中减去第二个操作数A - B 将得到 -10
*把两个操作数相乘A * B 将得到 200
/分子除以分母B / A 将得到 2
%取模运算符,整除后的余数B % A 将得到 0
++自增运算符,整数值增加 1A++ 将得到 11
自减运算符,整数值减少 1A-- 将得到 9

关系运算符

运算符描述实例
==检查两个操作数的值是否相等,如果相等则条件为真。(A == B) 为假。
!=检查两个操作数的值是否相等,如果不相等则条件为真。(A != B) 为真。
>检查左操作数的值是否大于右操作数的值,如果是则条件为真。(A > B) 为假。
<检查左操作数的值是否小于右操作数的值,如果是则条件为真。(A < B) 为真。
>=检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。(A >= B) 为假。
<=检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。(A <= B) 为真。

逻辑运算符

运算符描述实例
&&称为逻辑与运算符。如果两个操作数都非零,则条件为真。(A && B) 为假。
||称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。(A || B) 为真。
!称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。!(A && B) 为真。

位运算符

运算符描述实例
&按位与操作,按二进制位进行"与"运算。运算规则:(A & B) 将得到 12,即为 0000 1100
|按位或运算符,按二进制位进行"或"运算。运算规则:(A | B) 将得到 61,即为 0011 1101
^异或运算符,按二进制位进行"异或"运算。运算规则:(A ^ B) 将得到 49,即为 0011 0001
~取反运算符,按二进制位进行"取反"运算。运算规则:(~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。
<<二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。A << 2 将得到 240,即为 1111 0000
>>二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。A >> 2 将得到 15,即为 0000 1111

赋值运算符

运算符描述实例
=简单的赋值运算符,把右边操作数的值赋给左边操作数C = A + B 将把 A + B 的值赋给 C
+=加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数C += A 相当于 C = C + A
-=减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数C -= A 相当于 C = C - A
*=乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数C *= A 相当于 C = C * A
/=除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数C /= A 相当于 C = C / A
%=求模且赋值运算符,求两个操作数的模赋值给左边操作数C %= A 相当于 C = C % A
<<=左移且赋值运算符C <<= 2 等同于 C = C << 2
>>=右移且赋值运算符C >>= 2 等同于 C = C >> 2
&=按位与且赋值运算符C &= 2 等同于 C = C & 2
^=按位异或且赋值运算符C ^= 2 等同于 C = C ^ 2
=按位或且赋值运算符C |= 2 等同于 C = C | 2

杂项运算符

运算符描述实例
sizeof()返回变量的大小。sizeof(a) 将返回 4,其中 a 是整数。
&返回变量的地址。&a; 将给出变量的实际地址。
*指向一个变量。*a; 将指向一个变量。
? :条件表达式如果条件为真 ? 则值为 X : 否则值为 Y

C 中的运算符优先级

类别运算符结合性
后缀() [] -> . ++ - -从左到右
一元+ - ! ~ ++ - - (type)* & sizeof从右到左
乘除* / %从左到右
加减+ -从左到右
移位<< >>从左到右
关系< <= > >=从左到右
相等== !=从左到右
位与 AND&从左到右
位异或 XOR^从左到右
位或 OR
逻辑与 AND&&从左到右
逻辑或 OR
条件?:从右到左
赋值= += -= *= /= %=>>= <<= &= ^==
逗号,从左到右

5、 C 判断

判断语句

语句描述
if 语句一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。
if…else 语句一个 if 语句 后可跟一个可选的 else 语句,else 语句在布尔表达式为假时执行。
嵌套 if 语句您可以在一个 if 或 else if 语句内使用另一个 if 或 else if 语句。
switch 语句一个 switch 语句允许测试一个变量等于多个值时的情况。
嵌套 switch 语句您可以在一个 switch 语句内使用另一个 switch 语句。

? : 运算符(三元运算符)

6、C 循环

循环类型

循环类型描述
while 循环当给定条件为真时,重复语句或语句组。它会在执行循环主体之前测试条件。
for 循环多次执行一个语句序列,简化管理循环变量的代码。
do…while 循环除了它是在循环主体结尾测试条件外,其他与 while 语句类似。
嵌套循环您可以在 while、for 或 do…while 循环内使用一个或多个循环。

循环控制语句
C 提供了下列的循环控制语句。点击链接查看每个语句的细节。

控制语句描述
break 语句终止循环或 switch 语句,程序流将继续执行紧接着循环或 switch 的下一条语句。
continue 语句告诉一个循环体立刻停止本次循环迭代,重新开始下次循环迭代。
goto 语句将控制转移到被标记的语句。但是不建议在程序中使用 goto 语句。

7、C 函数

每个 C 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。

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

定义函数:
C 语言中的函数定义的一般形式如下:

在 C 语言中,函数由一个函数头和一个函数主体组成。返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。
有返回值函数定义:

return_type function_name( parameter list )	//有参函数
//void function_name( parameter list )		//无参函数
//函数名称:这是函数的实际名称。函数名和参数列表一起构成了函数签名。
//parameter list    参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
{
   body of the function	//函数主体:函数主体包含一组定义函数执行任务的语句。
}

函数声明:
函数定以后,必须先声明,在调用

调用函数:

函数调用,就是将封装好的好的函数,在需要的地方使用,直接调用函数名已实现某中特定的功能,有参函数需要注意参数的类型,和参数的个数需要对应,
函数参数:
如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。
形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。

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

1、在函数或块内部的局部变量
2、在所有函数外部的全局变量
3、在形式参数的函数参数定义中

局部变量
函数或块的内部声明的变量称为局部变量。它们只能被该函数或该代码块内部的语句使用。

全局变量
全局变量是定义在函数外部,通常是在程序的顶部。全局变量在整个程序生命周期内都是有效的,在任意的函数内部能访问全局变量。
局部变量和全局变量的名称可以相同,但是在函数内,如果两个名字相同,会使用局部变量值,全局变量不会被使用。

C 数组

定义:简单来讲就是一组相同类型数据的集合;数组也是需要先声明在使用,

数组声明:

type arrayName [arraySize]; #type 可以是任意有效的 C 数据类型,arraySize 必须是一个大于零的整数常量,

数组的初始化:

int one[N]={i1,i2,i3,i4……in}	#其中n可省略,就是定义无限大的数组;;in的下标n必须小于定义数组N,由于数组下标是由0开始计算的

多维数组

type name[size1][size2]...[sizeN];

传递数组参数与接收:

传递数组参数就是将定义好的数组当作形参传递;主要讲接收,将数组当作参数传递,就要在定义函数的时候制定好接收数组的参数,
以下三种方式接收:
1、形式参数是一个指针(您可以在下一章中学习到有关指针的知识):

void myFunction(int *param){}

2、形式参数是一个已定义大小的数组:

void myFunction(int param[10]){}

3、形式参数是一个未定义大小的数组:

void myFunction(int param[]){}

群号:992741643。
本人微信:
在这里插入图片描述
微信群正在维护建设阶段欢迎加入,如果添加不上可加我微信拉你进群。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值