本人自结C语言知识点

C语言程序设计

数据关键字:char字符型 1字节   short短整型 2字节  int整型 32位系统 4字节(16位系统2字节)

                      long长整型  4字节  float单浮点数 4字节  double双浮点数 8字节

                      struct结构体 union共用体 enum枚举有关

                      unsigned无符号(定义char short int long只能保存正数和0)

存储关键字:1.register 其修饰的变量为寄存器变量,尽量将其存储空间分配寄存器中,不定义数                          组

                      2.static:静态的意思,可修饰全局变量,局部变量,函数。

                      3.const.常量的意思,定义完禁止再赋值。

                      4.auto自动类型,基本不用。

                      5.extern外部的意思,一般在头文件、在函数和全局变量中使用。

其他关键字 1.sizeof:测量变量数组的占用空间大小。

                   2.typedef:重命名关键词

                   3.volatile:易改变的变量。

格式化输出字符   ‘\n’换行  ‘\t’跳格   ‘\\’表示‘\’   ‘%%’表示‘%’

进制的输出          %d十进制 %u十进制无符号 %x十六进制整数 %o八进制 %f float型 %lf double型

特殊应用             %3d 要求宽度3位,不足3位空格补齐;

                           %03d 要求宽度3位,不足三位,后面用空格补齐;

                           %-3d 宽度3位,不足三位,后面空格补齐;

                           %。2f 小数点后保留两位;

for循环             

 for (表达式1; 表达式2; 表达式3)           
{                                                                   
        语句;                                                             
}                             

(嵌套循环位外层循环i次,内层循环j次)   

                                 
Switch case语句:

switch(整型或字符型表达式)

{
   case     常量表达式1: 语句段1;break;
   case     常量表达式2: 语句段2;break;
   case     常量表达式3: 语句段3;break;

  default:  语句段n+1;                   break;
}

if else语句
if(判断条件)

{
语句块1
}else{
语句块2
}

while与do-while语句:

while (表达式)                                                            do{
   {                                                                                       循环语句;}
循环语句;                                                                      while(表达式)                                                        } 
                                                     

函数

一、什么是函数
函数是由一系列语句组合而成的,是一组语句的封装。函数的使用可以让我们避免重复的代码编写,让我们的程序更加的模块化。

其实,咱们从接触C语言开始的时候,就已经接触了函数了。每个C语言程序至少会有一个函数,那就是main()函数。main()函数是C语言程序的入口。除了main()函数,咱们在输出的控制台信息的时候用到的printf()也是一个函数。

函数还有很多叫法,比如方法、子例程或程序,等等。

二、函数的构成
函数是由函数类型,函数名,形参列表,函数主体这几部分构成的。

函数类型 函数名(形参列表){

        函数主体;

}

(1)函数类型,决定了函数最后return的返回值类型,比如是int型函数,那么在函数体里面要用return返回int型的值,如果是char型函数,则返回char型的值。如果不需要返回值的话,则函数类型写为void
(2)函数名,是我们在调用函数时使用的,就跟变量名一个道理
(3)参数列表,咱们在调用函数时,往函数里面传入的参数,这里的参数是可有可无的,写在函数定义的参数列表的参数叫做形式参数(形参),当我们调用函数的时候,填入的叫实际参数(实参)
(4)函数主体,用花括弧{}括起来的,包含所有组成函数的语句。如果函数不是void型的,则函数主体里面要有return语句返回对应类型的值。

三、函数的调用和声明

函数的调用方式:

函数名(实参列表);

        这里的实参列表,可以是变量(包括普通变量和指针变量),常量,表达式,函数等。实参列表里多个实参之间用逗号【,】来隔开。当定义函数时没有形参列表,则在调用函数的时候也不用传入实参。

由于C语言代码是从上往下依次执行的,所以对于函数的调用,咱们有两种方式

  1. 函数定义在函数调用之前,函数可以直接调用。
  2. 函数定义在函数调用之后,则需要在函数调用之前先声明被调用的函数之后再调用
  3.  头文件中所包含的函数及其用法(因内容过于多转载该作者的博客)

  4. 补充函数
    Windows.h 库函数的学习_Naile̶o̶n̶.的博客-CSDN博客

    C语言常见头文件汇总_c语言头文件大全_na小子叫坚强的博客-CSDN博客

数组

一、什么是数组
数组:一些具有相同类型的数据的集合

二、一维数组的定义和初始化
1.一维数组定义的一般形式:类型名  数组名[数组长度];

(1)类型名:指定数组中每个元素的类型

(2)数组名:数组变量的名称,是一个合法的标识符

(3)数组长度:一个整型常量表达式,设定数组的大小

如:int a[10];//定义了一个有10个整型元素的数组a

       float b[5];//定义了一个有5个单精度浮点型元素的数组b

2.一维数组的初始化:

1)其一般形式为:类型名  数组名[数组长度] = {初值表};     如:int arr[10] = {1,2,3,4,5,6,7,8,9,10};

(2)自动计算数组的长度:如果声明中未给出数组长度,编译器会把数组长度设置为刚好能容纳初始值的长度。

如:int arr[ ] = {1,2,3,4,5};等价于int arr[5] = {1,2,3,4,5};

(3)数组的初始化也可以只针对部分元素,如:int arr[5] = {1,2,3};那么数组的前三个元素分别为1,2,3,剩余的元素被初始化为0。

(4)如果初始化列表的项数>数组元素个数,编译器会视其为错误,如:int arr[5] = {1,2,3,4,5,6);//error

(5)指定初始化器:初始化指定元素。

#include
int main()
{
    int days[8] = { 31, 28, [4] = 31, 30, 31, [1] = 29};
    int i;
 
    for(i = 0; i < 8; i++)
    {
        printf("%d %d\n",i + 1, days[i]);
    }
 
     return 0;
}
编译并运行该代码,输出如下:

1 31

2 29

3 0

4 0

5 31

6 30

7 31

8 0

 指定初始化器的两个重要特性:

①如果指定初始化器后面有更多的值,那么这些值将被初始化指定元素后面的元素,即days[4]被初始化为31后,days[5]和days[6]将分别被初始化为30,31

②如果再次初始化指定元素,那么最后的初始化将会取代之前的初始化,即days[1]本来被初始化为28,但是days[1]又被后面指定初始化为29.

③如果没有指定元素大小,编译器会把数组的大小设置为足够装得下初始化的值,如:int arr[ ] = {1,[6] = 23}; arr数组有7个元素。

三、一维数组的使用:
1.[ ]为下标引用操作符。数组元素的引用要指定下标,其形式为:数组名[下标]。注意:数组下标从0开始,其取值范围为[0,数组长度-1],下标不能越界。用于识别数组元素的数字被称为下标、索引或者偏移量。所以a[0]的意思就是数组a中的第1个元素(生活中都是从1开始计数的),但是其实在计算机中应该中描述其为第0个元素。

2.看以下代码:

#include
int main()
{
    int arr[10] = {0};                  //数组的不完全初始化
    int i;                              //作为数组的下标
    int sz = sizeof(arr)/sizeof(arr[0]);//计算数组的元素个数
 
    //对数组内容进行赋值
    for(i=0; i<10; i++)
    {
        arr[i] = i;
    } 
 
   //输出数组的内容
   for(i=0; i<10; ++i)
   {
       printf("%d ", arr[i]);
   }
 
    return 0;
}

编译并运行该代码,输出如下:

0 1 2 3 4 5 6 7 8 9

(1)数组的大小是可以通过计算得到的。sizeof(arr)是整个数组的大小,sizeof(arr[0])是数组中一个元素的大小,两者相除得到的就是数组元素的个数。

(2)这段代码使用了一个循环给数组赋值,注意for循环中的第二条表达式(test)中不能写成i <= 10,这样会造成数组下标越界。C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,所以程序员写代码时,最好自己做越界的检查。

(3)另外,C不允许把数组作为一个单元赋给另一个数组,如:

#include
int main()
{
    int oxen[5] = {1, 2, 3, 4, 5};
    int yaks[5];
  
    yaks = oxen;//error
 
    return 0;
}
四、一维数组在内存中的存储
看以下代码:

#include
int main()
{
    int arr[5] = {0};
    int i;
 
    for(i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    {
       printf("&arr[%d] = %p\n", i, &arr[i]);
    }
 
    return 0;
}
编译并运行该代码,输出如下:

随着数组下标的增长,元素的地址,也在有规律的递增。因为arr数组的类型为int,所以每个地址之间相差4个字节。由此可以得出结论:数组在内存中是连续存放的
五、二维数组的定义和初始化

1.C语言支持多维数组,最常见的多维数组为二维数组。二维数组本质上是以数组作为数组元素的数组,即“数组的数组”。二维数组的定义形式为:类型名 数组名[行长度][列长度];如:int arr[3] [2];//定义了一个二维数组,3行2列,共6个元素。

2.二维数组的初始化:

(1)分行赋初值:一般形式为:类型名 数组名[行长度][列长度]={{初值表0},{初值表1},...,{初值表n}};

如:int arr[2][2] = { { 1,  2} , {3, 4} };

此时arr数组中各元素为:1  2

                                        3  4

二维数组的初始化,也可以只针对部分元素,如:int arr[2][2] = { {1, 2},{} };此时arr数组的第0行的元素的值分别为1,2;而第一行的元素的初值默认为0。

(2)顺序赋初值:一般形式为:类型名 数组名[行长度][列长度]={初值表};

如:int arr[2][2] = { 1, 2, 3, 4 };等价于int arr[2][2] = { { 1,  2} , {3, 4} };

       int arr[2][2] = { 1, 2, 0, 0 };等价于int arr[2][2] = { {1, 2},{} }; 

(3)注意:二维数组初始化时,如果对全部元素都赋了初值,或分行赋初值时,在初值表中列出了全部行,就可以省略行长度。

如:int arr[ ][3] = {1,2,3,4,5,6,7,8,9};等价于int arr[3][3] = {{1,2,3},{4,5,6},{7,8,9}};

不可以省略列的长度!!!

六、二维数组的使用
1.引用二维数组的元素要指定两个下标,即行下标和列下标,形式为:数组名[行下标][列下标]。行下标的合理取值范围为[0,行长度-1],列下标的合理取值范围为[0,列长度-1]。比如a[0][0]的意思是第1行第1列的元素(生活中从1开始计数),但是其实在计算机中应该中描述其为第0行第0列的元素。

用两重循环来给二维数组赋值:

#include
int main()
{
    int arr[2][2] = {0};
    int i, j;
 
    for(i = 0; i < 2; i++)
    {
       for(j = 0; j < 2; j++)
       {
          arr[i][j] = i * 4 + j;
       }
    }
 
    for(i = 0; i < 2; i++)
    {
       for(j = 0; j < 2; j++)
       {
           printf("%d ", arr[i][j]);
       }
    }
 
    return 0; 
}

编译并运行代码,输出如下:

0 1 4 5

七、二维数组在内存中的存储:
看以下代码:

#include
int main()
{
    int arr[2][2];
    int i, j;
 
    for(i = 0; i < 2; i++)
    {
       for(j = 0; j < 2; j++)
       {
           printf("&arr[%d][%d] = %p\n", i, j,&arr[i][j]);
       }
    }
 
    return 0; 
}

编译并运行该代码,输出如下:

由此,我们可以分析,二维数组在内存中也是连续存储的。所以,二维数组可以整体看成一个一维数组,如图:

 八、数组作为函数参数
1.数组名是数组首元素的地址,数组名是一个地址常量。

2.两个例外:

(1)sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。

(2)&数组名,取出的是数组的地址。&数组名,数组名表示整个数组

除了这 两种情况之外,其它所有的数组名都表示数组首元素的地址,如:*数组名等等
看以下代码以及结果:

①test()中打印的是长度为4,更加印证了数组作为函数参数时,没有把整个数组都传过去,而是把数组中首元素的地址传过去了,此处的地址是用十六进制表示的整型常量,所以大小为4byte。

②main()中打印的长度为40,是因为sizeof(数组名)计算的是整个数组的大小,数组中有10个int型的元素,所以10*4=40

③函数定义头中的形参int arr[]里面的[],它的里面可以什么都不填,也可以填一个任意数,因为它没有意义,比如说形参写成int arr[20]也是可以的,但是为了代码的可读性更强,我们不建议这样写。

 其实,test()的形参还可以这样写:

void test(int* arr)
{
    printf("%d\n",sizeof(arr));
}
因为数组名是数组首元素的地址,我们用指针来接收arr的首元素地址更好。注意:只有在函数原型或函数定义头中,才可以用int arr[]代替int* arr。

3.在函数原型中可以省略参数名,所以下面这4种写法等效:

void test(int* arr);
void test(int arr[]);
void test(int*);
void test(int []);

指针

  • 32位电脑的内存地址范围是 0 ~ 232 - 1
  • 64位电脑的内存地址范围是0 ~ 264 -1
  • 每一个单位的内存空间的大小是 1个字节
  • 字长不同的电脑,指针所占空间的大小也不一样,32位电脑上,一个指针变量占 4个字节,64位电脑上,占 8个字节

你可能感兴趣的:(c语言)