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语言代码是从上往下依次执行的,所以对于函数的调用,咱们有两种方式
头文件中所包含的函数及其用法(因内容过于多转载该作者的博客)
补充
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 []);
指针