Fork me on GitHub

指针

变量的内存地址

在C语言中,要获得变量的地址,需要用到**取地址运算符(Address Operator),即&.

1
printf("%p",&a);

%p格式符,表示输出变量a,b,c的地址值

地址值是用一个十六进制的无符号整数表示的,其字长一般与主机字长相同

变量的地址:变量在内存中所占内存空间的首地址

变量的值:变量在存储空间中存放的数据

变量的名字

指针的变量的定义和初始化

指针:存放变量的一种特殊类型的变量。

指针变量:具有指针类型的变量,是专门用于存储变量的地址值的变量

定义变量的形式:

类型关键字 * 指针变量名

指针变量的基类型:类型关键字代表变量要指向的变量的数据类型,

指针的初始化

指针变量未初始化意味着指针变量的值为一个随机值。

为了避免忘记指针初始化带给系统带来的潜在危险,为了防止指针乱指一气,习惯上在定义指针变量的同时将其初始化为NULL(在stdio.h中定义为零值得宏)

指向某变量的指针变量,通常简称为某变量的指针

虽然指针变量中存在的是变量的地址值,二者在数值上相等,但在概念上变量的指针不等同于变量的地址。

变量的地址是一个常数,不能对其赋值,二变量是一个变量,其值是可以改变的.

指针变量只能指向同一基类型的变量

对指针初始化的方法

  • 直接初始化
  • 间接初始化

直接初始化

类型:int *pa = &a;

间接初始化

类型:int *pa;

​ pa = &a;

间接寻址运算符

直接寻址:直接按变量名或者变量的地址存取变量内容的访问方式

scanf(“%d”,&a);

printf(“%d”,a);

间接寻址:用过指针变量间接存取它所指向的变量的访问方式

指针运算符,也称间接寻址运算符即为 * 。间接寻址运算符 * 用来访问指针变量指向的变量的值

通过 * 可以对指针变量实现解引用,即访问指针变量

C语言指针和数组

指针和数组

C语言其高效性就在于其有指针这一利器,所以我们要好好弄懂指针和数组的区别

指针和一维数组的关系

数组名的意义及其访问一维数组的方法

数组名:数组名代表了存放数组的连续空间的首地址

对数组的访问可以通过两种方式:下标法和指针

第一种:下标法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
int main()
{
int a[5],i;
printf("Input five numbers");
for(i=0;i<5;i++)
{
scanf("%d",&a[i]); /*下标法写入数组元素*/
}
for(i=0;i<5;i++)
{
printf("%d",&a[i]); /*下标法读出数组元素*/
}
return 0;
}

第二种:指针

因为数组名a代表数组的首地址,即元素a[0]的地址(&a[0])

因此,可以通过*a(此处 *为解引用符)来获得首地址a所指的储存单元中储存的内容

原因数组元素之所以能够通过这种方法来引用,是因为数组的下标运算符[]实际上就是以指针作为操作数的

类型 : *(a+i)意义为引用数组首地址后第i个元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
int main()
{
int a[5],i;
printf("Input five numbers");
for(i = 0; i < 5; i++)
{
scanf("%d",a+i); /*这里的a+i等于a[i]*/

}
for(i = 0; i < 5; i++)
{
printf("%d",*(a+i); /*这里的a+i等于a[i]*/

}
return 0;

}

指针与二维数组的关系

运算符和表达式

运算符

  • 一个操作数的运算符是一元运算符
  • 两个操作数的运算符是二元运算符
  • 三个操作数的运算符是三元运算符

条件运算符是C语言唯一的一个三元运算符,除此之外都是二元运算符

C运算符

C语言提供一下运算符:

  1. 算数运算符 (+ - * / % ++ –)

  2. 关系运算符 (> < == >= <= !=)

  3. 逻辑运算符 (! && ||)

  4. 位运算符 (<< >> ~ | ^ &)


  5. 赋值运算符 (= 及其扩展形式)

  6. 条件运算符 (?:)

  7. 逗号运算符 (,)

  8. 指针运算符 (*和&)

  9. 求字节数运算符 (sizeof)

  10. 强制类型转换运算符 ((类型))

  11. 成员运算符 (.->)

  12. 下标运算符 ([])

  13. 其他 (如函数调用运算符())

基本的算数运算符

最常用的算术运算符

运算符 含义 举例 结果
+ 正号运算符(单目运算符) +a a的值
- 负号运算符(单目运算符) -a a的算数负数
* 乘法运算符 a * b a和b的乘积
/ 除法运算符 a / b a除以b的商
% 求余运算符 a % b a除以b的余数
+ 加法运算符 a + b a和b的和
- 减法运算法 a - b a和b的差

说明:

  • 由于键盘无×号,运算符×以*代替
  • 由于键盘无÷号,运算符÷以/代替。两个实数相除的结果是双精度实数,两个整数相除的结果为整数。但是,如果除数或被除数中有一个负数,则舍入的方向是不固定的。
  • %运算符要求参加运算的运算对象(即操作数)为整数,结果也是整数
  • 除%以外的运算符的操作数都可以是任何算术类型

自增(++),自减(–)运算符

自增,自减运算符的作用是使变量的值加1或减1,例如:

++i,–i (在使用i之前,先使i的值加(减)1)

i++,i– (在使用i之后,使i的值加(减)1)

算术表达式和运算符的优先级与结合性

用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语法规则的式子成为C算术表达式

C语言规定了运算数的优先级,还规定了运算符的结合性


算术运算符——>自左至右

赋值运算——>自右向左

不同类型数据间的混合运算

如果一个运算符两侧的数据类型不同,则先自动进行类型转换,是两者成为同一类型,然后进行运算。


低——————————————————————————————>高

int(char,short)–>unsigned int–>long–>unsigned long–>double(float)–>long double


按照从高到低的顺序给各种数据类型分等级,依次为:long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int 和 int。这里有一个小小的例外,如果 long 和 int 大小相同,则 unsigned int 的等级应位于 long 之上。char 和 short 并没有出现于这个等级列表,是因为它们应该已经被升级成了 int 或者 unsigned int。


当是从低级转换为高级时,是自动转换

从高级转换为低级时,需要进行强制转换


强制转换

类型:

(类型名)(表达式)

数组

一维数组的定义和初始化

数组:是一组具有相同类型的变量的集合

数组名:用以识别该组相同类型数据的名字

数组元素:构成数组的每个数据项

数组下标

数组的基类型:数组中元素的类型

数组的维数:下标的个数

一维数组的格式:类型 数组名[元素个数];


注意,C语言中的下标都是从0开始的

为了访问数组中的每个元素,可以通过数组名加上标值得形式,在数组名的右侧添加方括号,然后将下标值写在其中。


在定义数组时不能使用变量定义数组的大小

一维数组的初始化

定义但未进行初始化的数组元素的值仍然是随机数。

初始化方法

将元素初值放在=后面用一对花括号括起来的初始化列表中。

1
int score[5] = {90,80,70,100,95};

初始化的值不能多于数组元素个数,也可以不规定数组元素个数,机器会自动识别;

当初始化的值不够数组元素个数时,机器会自动将其他的补位0

二维数组的定义和初始化

定义一般格式

类型 数组名[第一维长度] [第二维长度]

第一维长度代表数组的行数,第二维长度代表数组的列数

计算机中数组计算所占内存的方法

  • 一维数组在内存中占用的字节数为:数组长度 * sizeof(基类型)
  • 二维数组在内存中占用的字节数为:第一维长度 * 第二维长度 * sizeof(基类型)

相数组输入和输出数据

原理:由于C语言中不带下标的数组名具有特殊的含义,它代表数组的首地址,因此不能整体引用一个数组,每次只能引用指定下标值得数组元素

输入数据

1
2
3
4
5
6
7
for(i = 0; i < 3; i++)
{
for(j = 0; j < 4; j++)
{
scanf("%d", &matrix[i][j]);
}
}

输出数据

1
2
3
4
5
6
7
for(i = 0; i < 3; i++)
{
for(j = 0; j < 4; j++)
{
printf("%4d", &matrix[i][j]);
}
}

注意

当对数组的全部元素进行初始化时,第一维的长度声明可以忽略

数组的第二维的长度声明永远不能省略

向函数传递一维数组

数组元素和基本型变量一样,既可以出现在任何合法的C表达式中,也可用作函数参数

数组作为参数的方式

若要把一个数组传递给一个函数,那么只要使用不带方括号的数组名作为函数实参调用函数即可

注意,仅仅是数组名,不带方括号和下标

按值传递

由于数组名代表数组第一个元素的地址,因此用数组名作函数实参实际上是将数组的首地址传给被调函数

注意:数组作为函数形参时,数组的长度可以不出现在数组名后面的方括号内,通常用另一个整型形参来指定数组的长度

向函数传递二维数组

当形参被声明为二维数组时,可以省略数组的第一维长度声明,但不能忽略数组的第二维的长度声明

文件操作

二进制文件和文本文件

文件:是由文件名来识别,因此只要声明了文件名,就可以读出或写入数据。只要文件名不同,就不会发生冲突。

C语言提供了两种文件类型:文本文件和二进制文件

文本文件

文本文件又名(ASCLL码文件)

特点:文本文件中的每一位数字都单独占用一个字节的存储空间。

优点:文本文件可以很方便地被其他程序读取,包括文本编译器、Office办公软件等,且其输出与字符一一对应,一个字节代表一个字符,便于对字符进行逐个处理,便于输入字符,但一般占据的空间比较大,且需环肥ASCLL码与字符键的转换时间。

二进制文件

特点:把整个数字作为一个二进制数来储存,并非数值的每一位数字都占用单独的储存空间

优点:以二进制文本输出数据,可以节省额外的空间和转换时间,但因为一个字节并非对应一个字符,不能直接输出其对应的字符形式

字节流

定义:无论一个C语言文件内容是什么,它一律把数据看成是由字节构成的序列,即字节流。

因此C语言文件又被称为流式文件

两种文件储存系统

C语言有缓冲型非缓冲型两种文件系统

第一种,缓冲型

缓冲型文件缓冲系统是指系统自动在内存中为每一个正在使用的文件开辟一个缓冲区,作为程序与文件之间数据交换的中间媒介。也就是在读写文件时,数据先送到缓冲区,再传递给C语言程序或外存上。缓冲文件系统利用文件指针标识文件。

缓冲型文件系统痛的文件操作,也称为高级文件操作,高级文件操作函数是ANSIC定义的可移植的文件操作函数,具有跨平台和可移植的能力,可解决大多数文件操作问题。

第二种,非缓冲型

非缓冲文件系统是不会自动设置文件缓冲区的,缓冲区必须由程序员自己设定。非缓冲文件系统没有文件指针,它使用称为文件号的整数来标识文件

文件的打开与关闭

在使用文件之前必须先打开文件。函数fopen()用来打开文件:

1
FILE *fopen(const char *filename, const char *mode)

返回值类型:fopen()的返回值是一个文件指针

FILE是stdio.h中定义的结构体类型,封装了与文件有关的信息,如文件句柄、位置指针及缓冲区等。缓冲文件系统的每个被使用的文件在内存中开辟一个缓冲区,用来存放文件有关的信息,这些现在被保存在一个FILE结构类型的变量中。

fopen()的两个形参:第一个形参filename表示文件名,可包含路径文件名两部分。第二个形参mode表示文件的打开方式,其取值如下表:

字符 含义
“r” 以只读的方式,打开文本文件。以“r”方式打开的文件,只能读出,而不能向该文件写入数据。该文件必须是已经存在的,若文件不存在,则会出错
“w” 以只写方式,创建并打开文本文件,已存在的文件将被覆盖。以“w”方式打开文件时,无论文件是否存在,都需创建一个新的文件,只能写入数据
“a” 以只写方式,打开文本文件,位置指针移到文件末尾,向文件尾部添加数据,原文件数据保留。若文件不存在,则会出错
“+” 与上面的字符串组合,表示以读写方式打开文本文件。即可向文件中写入数据,也可从文件中读出数据
“b” 与上面的字符串组合,表示打开二进制文件

以向在D盘中的demo.text读写为例

1
2
fp = fopen("D:\\demo.text","a+");//已读写方式打开demo
fp = fopen("D:\\demo.bin","ab+");//以二进制方式打开demo.bin

文件指针fp是指向FILE结构类型的指针变量定义如下

FILE *fp;

因为操作系统对于同时打开的文件数目是有限制的,所以在文件使用结束后必须关键文件,否则会出现意想不到的错误。在C语言中,函数fclose()用来关闭一个由函数fopen()打开的文件

1
int fclose(FILE *fp);

函数fclose()返回一个整型数。当文件关闭成功时,返回0值,否则返回一个非0值。

因此可以根据函数的返回值判断文件是否关闭成功。

文件内容拓展

文件的随机读写

顺序文件处理:在顺序文件处理过程中,数据项是一个接着一个进行读取或者读写。

随机访问:允许在文件中随机定位,并在文件的任何位置直接读写数据

方法:为了实现文件的定位,在每一次打开的文件中,都有一个文件位置指针也称文件位置标记,用来指向当前读写文件的位置,它保存了文件中的位置信息。

eg 这里给出两个函数来定义的文件位置指针。

1
2
int fseek(FILE *fp, long offset, int fromwhere);
void rewind(FILE *fp);

fseek()函数

功能:函数fseek()的功能是将fp的文件位置指针从fromwhere开始移到offset个字节,指示下一个要读取数据的位置

参数的意义offset是一个偏移量,它告诉文件位置指针要跳多少个字节。offect为正时,向后移动,为负时,向前移动。AXSI C要求位移量offset是长整型数据(常量后加L)。fromwhere用于确定偏移量计算的起始位置,它的情况可能有三种:

  • SEEK_SET或0,表示文件开始处
  • SEEK_CUR或1,代表文件当前的位置
  • SEEK_END或2,代表文件结尾处

rewind()函数

功能:将文件位置指针指向文件首字节,即重置位置指针到文件首部

如果函数fseek()调用成功,则返回0值,否则返回非0值

ftell()函数

功能:用于读取当前文件位置指针的函数,用于相对于文件起始位置的字节偏移量来表示返回的当前文件位置指针

原型

1
long ftell(FILE *fp);

fflush()函数

功能:fflush()函数的功能是无条件地把缓冲区中的所有数据写入物理设备

通过下列的这个程序实例,可以实现对文件中的数据的搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<stdio.h>
#include<stdlib.h>
typedef struct date
{
int year;
int month;
int day;
}DATE;
typedef struct student
{
long studentID;
char studentName[10];
char studentSex;
DATE birthday;
int score[4];
float aver;
}STUDENT;
void SearchinFile(char fileName[],long k);
int main()
{
long k;
printf("Input the searching record number:");
scanf("%ld",&k);
SearchinFile("D:\\student.txt",k);
return 0;

}
void SearchinFile(char fileName[],long k)
{
FILE *fp;
int j;
STUDENT stu;
if((fp = fopen(fileName,"r")) == NULL)
{
printf("Faliure to open %s!\n",fileName);
exit(0);
}
fseek(fp,(k-1)* sizeof (STUDENT), SEEK_SET);
fread(&stu, sizeof(STUDENT),1,fp);
printf("%10ld%8s%3c%6d/%02d/%02d",stu.studentID,stu.studentName,stu.studentSex,
stu.birthday.year,stu.birthday.month,stu.birthday.day);
for(j = 0; j < 4; j++)
{
printf("%4d",stu.score[j]);
}
printf("%6.1f\n",stu.aver);
fclose(fp);

}

排序和查找

排序

排序:是把一系列无序的数据按照特定的顺序重新排列为有序序列的过程

交换法排序

特点:性能比较低,但是易于理解,是选择法的基础

1
2
3
4
5
6
7
8
for(i = 0; i < n-1; i++)
{
for(j = i+1; j < n; j++)
{
若score[j] > score[i]
则交换 score[j] 和 score[i] 的值
}
}

选择排序法

特点:执行次数少,不过较难理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void DateSort(int score[], int n)
{
int i, j, k, temp;
for(i = 0; i < n-1; i++)
{
k = i;
for(j = i + 1; j < n; j++)
{
if(score[j] > score[k])
{
k = j;
}
}
if(k != i)
{
temp = score[k];
score[k] = score[i];
score[i] = temp;
}

}
}

对信息进行排序时,通常只使用信息的一个子项作为键值(Key Value),由键值决定信息的全部子项的排列顺序

查找

查找:在数组中搜索一个特定元素的处理过程

线性查找(Linear Search)

特点:算法简单直观,但效率较低

查找键:查找的基本过程是利用循环顺序扫描整个数组,依次将每个元素与待查找值进行比较;若找到就停止循环

1
2
3
4
5
6
7
int i;
for(i = 0; i < n; i++)
{
if(number == X)
return i;

}

折半查找(Binary Search)

特点:稍微复杂,但效率很高

注意:折半查找只能在已经排好序的数值中查找

折半查找基本思想:首先选取位于数组中间的元素,将其与查找键进行比较。如果它们的值相等,则查找建以被找到,返回数组中间元素的下标。否则,将查找的区间缩小为原来区间的一半,即在一半的数组元素中查找

1
2
3
4
5
6
7
8
9
10
11
int low = 0, high = n-1,mid;
while(low <= high)
{
mid = (high + low) / 2;
if(x > num[mid])
low = mid + 1;
else if (x < num[mid])
high = mid + 1;
else
return mid;
}

C语言数据类型

C语言程序处理的数据类型有常量(Constant)和变量(Variable)两种形式

常量


常量类型 实例 备注
整型常量 10,-30,0 包括正整数,负整数和零在内的所有整数
实型常量 3.14 -0.56 由于计算机的实型数是以浮点类型表示,实型常量也可以称为浮点数
字符常量 ‘x’,‘X’,‘0’ 用一对单引号括起来的任意字符
字符串常量 ”Hello!“ 用一对双引号括起来的零个或多个字符

补充

  • 整数(有符号) ——>int
  • 无符号整数常量——>int + 整数 + U或u
  • 长整型 ——>int + 整数 + L或l
  • 无符号长整型——>int + 整数 + Lu
  • 十进制小数——>必须带小数点
  • 指数形式——>eg:1e-10 用e或E代表以10位底的指数
  • 单精度(float)——>常数值后加F或f
  • 双精度(double)——>实型常量没有明确表明类型都是双精度
  • 长双精度(long double)——>12.5L 常数值后跟L或l来表示

字符常量

字符常量有两种:普通字符和转义字符

常见的以“\”开头的特殊字符

转义字符 字符值 输出结果
\ ‘ 一个单撇号(‘) 输出单撇号字符’
\ ‘’ 一个双撇号(“) 输出双撇号字符”
\ ? 一个问号(?) 输出问号字符?
\ \ 一个反斜线(\) 输出反斜线字符\
\ a 警告(alert) 产生声音或视觉信号
\ b 退格(backspace) 将光标当前位置后退一个字符
\ f 换页(form feed) 将光标当前位置移到下一页的开头
\ n 换行 将光标当前位置移到下一行的开头
\ r 回车(carriage return) 将光标当前位置移到本行的开头
\t 水平制表符 将光标当前位置移到下一个Tab位置
\ v 垂直制表符 将光标当前位置移到下一个垂直制表对齐点
\ 0,\00或\000其中o代表一个八进制数字 与该八进制码对应的ASCLL字符 与该八进制码对应的字符
\xh[h…]其中h代表一个十六进制数字 与该十六进制码对应的ASCLL字符 与该十六进制码对应的字符

变量

变量名的命名规则


变量的名字就是标识符

  • 标识符只能由英文字母,数字和下划线_组成
  • 标识符必须以字母或下划线开头
  • 不允许使用C关键字作为标识符命名
  • 标识符可以包含任意多个字符,但一般会有最大限制

标识符是区分大小写的即大小写敏感的

  1. 标准C规定所有的变量必须在第一条执行语句之前定义
  2. 在为变量赋值时,等号两边的空格不是必须的,增加程序的可读性
  3. C语言允许在定义变量时对变量进行初始化(为其赋值)

整型变量的符号属性

类型 字节数 取值范围
int 4 -2 147 483 648~2 147 483 647
unsigned int 4 0 ~ 4 294 967 295
short 2 -32 768 ~ 32 767
unsigned short 2 0 ~ 65 535
long 4 -2 147 483 648 ~ 2 147 483 647
unsigned long 4 0 ~ 4 294 967 295
long long 8 -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807
unsigned long long 8 0 ~ 18 446 744 073 709 551 615

字符变量

类型 字节数 取值范围
signed char 1 -128~127
unsigned char 1 0~255

实型变量

类型 字节数 有效数字 数值范围(绝对值)
float 4 6 0以及1.2*10^-38 ~ 3.4 * 10^38
double 8 15 0以及2.3*10^-308 ~ 1.7 * 10^308
long double 8 15 0以及2.3*10^-308 ~ 1.7 * 10^308
long double 16 19 0以及3.4 * 10^-4932 ~ 1.1 * 10^4982

结构体

结构体和共用体就是C语言提供的用于处理复杂数据类型的方式允许用户自定义数据类型在C语言中为构造数据类型(也称复合数据类型

它允许用户根据自己的需要利用已有的基本数据类型在制造出自己所需的数据类型。用于表示链表,树,堆栈等复杂的数据对象。

结构体的定义

数组:是由同类型的数据构成的一种数据结构,适合于对具有相同属性的数据进行批处理

结构体:是将不同类型的数据成员组织到统一的名字之下,适合于对关系密切、逻辑相关、具有相同或者不同属性的数据进行处理

共用体:虽然也能表示逻辑相关的不同类型的数据集合,但其数据成员是情形互斥的,每一刻只有一个数据成员起作用

结构体变量的定义

结构体模板的标准格式:

1
2
3
4
5
6
7
8
9
struct 结构体名
{
数据类型 成员1的名字;
数据类型 成员2的名字;
数据类型 成员3的名字;
……
数据类型 成员n的名字;

};/*注意,这里的分号不能忘了写*/

结构体标签:结构体的名字,作为用户自定义的结构体类型的标志,用于与其他结构体类型相区别。

结构体的各种信息是在{}中声明的

结构体成员:构成结构体的变量,每个结构体成员都有一个名字和相应的数据类型,其命名必须遵循变量的命名规则

注意,结构体模板只是声明了一种数据类型,定义了数据的组织形式,并未声明结构体类型的变量


C语言允许一下两种方法定义结构体变量:

第一种:先声明结构体模板,再定义结构体变量

1
2
3
4
5
6
7
8
9
10
11
struct 结构体名
{
数据类型 成员1的名字;
数据类型 成员2的名字;
数据类型 成员3的名字;
……
数据类型 成员n的名字;

};
struct student stu1

第二种:在声明结构体模板的同时定义结构体变量

1
2
3
4
5
6
7
8
9
struct 结构体名
{
数据类型 成员1的名字;
数据类型 成员2的名字;
数据类型 成员3的名字;
……
数据类型 成员n的名字;

}stu1;

用typedef(关键字)定义数据类型

关键字typedef用于为系统固有的或程序员自定义的数据类型定义一个别名。

通常数据类型的别名都是全英文大写的

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef int INTEGER; /*将int重新命名为INTEGER*/
typedef struct student STUDENT;/*将自己制造的student类型重命名为STUDENT*/
or
typedef struct student
{
数据类型 成员1的名字;
数据类型 成员2的名字;
数据类型 成员3的名字;
……
数据类型 成员n的名字;

}STUDENT;

上述的定义STUDENT的两个代码是等价的;

typedef只是为一种已存在的类型定义一个名字而已,并未定义一种新的数据类型

嵌套的结构体

嵌套的结构体就是在一个结构体内包含了另一个结构体作为其成员

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct date
{
int year;
int month;
int day;
}DATE;
typedef struct student
{
char name[];
int ID;
DATE birthday;
}STUDENT

结构体变量的引用


C语言规定,不能将一个结构体变量作为一个整体进行输入,输出操作,只能对每个具体的成员进行输入,输出操作


访问格式: 结构体变量名 . 成员名

当引用嵌套体时,必须一级一级地通过访问格式找到最底层的成员后再引用

eg:stu1.birthday.day


C语言允许对具有相同结构体类型的变量进行整体赋值。

stu1 = stu2;

这样是非法的;

并非所有的结构体成员都可以使用赋值运算符来赋值,对字符数组类型成员进行赋值时,必须使用字符串处理函数strcpy()

结构体变量也和基本的变量一样有作用域,在函数外定义的结构体变量是全局声明,在函数内部定义的结构体变量是局部声明

结构体变量的地址是结构体变量所占内存空间的首地址,而结构体成员的地址值与结构体成员在结构体中所处的位置及其该成员所占内存的字节数有关

结构体所占内存的字节数

有四字节对齐原则

结构体数组的定义和初始化

结构体数组的定义

与基本的数据类型相同,结构体也是有其对应的数组的,是代表有与结构体中每个元素相同的一系类结构体的集合

结构体数组的初始化

可以在定义结构体数组时就对其进行初始化,和字符数组一样

也可以通过scanf()函数进行初始化,不过要注意每个结构体元素对应的数据类型

指向结构体的指针

结构一也是有指针的,定义结构体指针的方法如下:

第一种:STUDENT *pt = stu;

第二种:STUDENT *pt = &stu[0];

第三种:STUDENT *pt;

​ pt = stu;

以上三种定义的方法都是等价的

向函数传递结构体

第一种:用结构体的单个成员作为函数参数,向函数传递结构体的单个成员

第二种:用结构体变量作为函数参数,向函数传递结构体的完整结构

第三种:通过结构体指针或结构体数组作为函数参数,向函数传递结构体的地址

1

0

C语言常用工具

注释

  • 用/ * 和 * /包含起来的内容成为注释
  • 在/ 和 * 之间不能有空格

C++风格的注释则是以//开始,只能注释一行

注释不可以嵌套,即不能在一个注释中嵌套另一个注释

sizeof

sizeof是C语言的关键字,不是函数名。sizeof()是C语言提供的专门用于计算制定数据类型字节的运算型。
使用方法

1
printf("xx %d",size of (xx));

宏常量

  • 在程序中直接使用的常数,成为幻数
  • 为了保护良好的程序设计风格,可把幻术定义为宏常量或const常量

eg :#define PI 3.14159

  • 宏定义的一般形式为#define 标识符 字符串
  • 在用#define定义一个标识符和一个字符串,程序进行时遇到标识符时会被识别为字符串
  • 宏定义中标识符被称为宏名 ,习惯用字母全部大写的单词命名宏常量。将程序中出现字符串代替标识符的过程称为宏替换

宏定义中的宏名与字符串之间可有多个空白符,但无需加等号,且字符串后一般不以分号结尾,,因此宏定义不是C语句,而是一种编译预处理命令

如果字符串加分号,在替换时会连同“;”一起替换

常用的标准数学函数

函数名 功能
sqrt(x) 计算x的平方根,x应大于等于0
fabs(x) 计算x的绝对值
log(x) 计算lnx的值,x应大于0
log10(x) 计算lgx的值,x应大于0
exp(x) 计算e^x的值
pow(x,y) 计算x^y的值
sin(x) 计算sinx的值,x的弧度值,而非角度值
cos(x) 计算cosx的值,x的弧度值,而非角度值

域宽m

输出域宽m(m为整数)

作用:指定输出项输出十所占的列数

类型 作用
%md 若m为正整数,当输出数据的域宽小于m时在域内内向右靠齐,左边多余位补空格;当输出数据的域宽大于m时,按实际宽度全部输出
%0md 若m前有前导号0,则在左边多余位补0
%-md 若m为负整数,则输出数据在域内向左靠齐

显示精度.n

类型 作用
%.nf 用于指定输出浮点数的小数位数
%.ns 用于指定从字符串左侧开始截取的子串字符的个数
  • Copyrights © 2015-2023 dwx
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信