第一步:编辑源代码(使用vi或者其他编辑器)
第二步:编译。编译就是用编译器把源程序转化为可执行程序的过程,编译要用到编译器。我们在linux中使用编译器一般是gcc。
第三步:执行编译生成的可执行程序,执行方式是./hello
第四步:调试。当你执行后发现程序结果不对,不是自己想要的,这时候就是返回来看源代码哪里不对。然后修改,在编译执行,再看结果。如此循环至结果正确。
1、打印下面图形
*
***
*****
***
*
解答:
1)空格占位打印
2)for循环控制占位,
第一个循环i=1~N,打印N-i+1个空格,2i-1个*
第二个循环i=1~N,打印i个空格,2(N-i+1)-1个*
2、打印下面的图形
\--------------------------------
** www.link-embed.com **
** Aston **
\--------------------------------
解答:用空格控制
总结:
1、使用到的技术主要是printf中\n换行和\接续符。
2、题目目的主要是为了熟悉C语言程序的编辑、编译、执行、调试过程。
3、C语言中的注释,短的用//,多行的用/* */。
icnlude(包含) 头文件包含
int(integer,整数) 定义了整型这个数据类型,用来表示一个整数的类型叫整型。
char(character,字符) 字符型数据类型
return(返回)
当我们裸机安装了Windows,并且在Windows中安装了虚拟机软件VMWare,并且在虚拟机中安装Ubantun后,我们一般在Windows中编辑源代码,而在Linux中编译,执行源代码。这时候就需要在Windows和Linux之间进行交互。 怎么来进行交互呢?之前通过smb服务器,现在通过VMWare的共享文件夹就可轻松实现。
数学中数是有符号的,有正数和负数之分。所以计算机中的数据类型也有符号,分为有符号数和无符号数。
有符号数:
整形:
signed int(简写为 int)
signed long,也写作signed long int,(简写为long)
signed short,也写作signed short int(简写为short)
signed(表示signed int)
浮点型:
signed float(简写为float)
signed double(简写为double)
字符型:
signed char(简写为char)
无符号数:
整形:
整形有无符号数,用来表示一些编码编号之类的东西。譬如身份证号,房间号
unsigned int(没有简写)
unsigned long int(简写unsigned long)
unsigned short int(简写为unsigned short)
浮点数:
没有无符号浮点数。也就是说,小数一般只用在数学概念中,都是有符号的。
字符型:
字符型有无符号数
unsigned char(没有简写)
注意:对于整形和字符型来说,有符号数和无符号数表示的范围是不同的。譬如字符型,有符号数范围是-128127,无符号数的范围是0255
+ 加号
- 减号
* 乘号
/ 除号,相除以后的商
% 取余符号,相除以后余数是几
() 括号括起来优先级最高,先计算
+= a = a + b; 等同于 a += b;
-= a = a - b; 等同于 a -= b;
*= a = a * b; 等同于 a *= b;
/= a = a / b; 等同于 a /= b;
%= a = a % b; 等同于 a %= b;
bianliang1 = bianliang1 + bianliang2;
bianliang1 += bianliang2;
== 等于
!= 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于
+ ++
a++; 等同于 ++a; 等同于 a = a + 1; 等同于 a += 1;
+ --
+ a--; 等同于 --a; 等同于 a = a - 1; 等同于 a -= 1;
1、自己查找资料或写代码测试,总结++放在前面和后面的区别(a++和++a区别)
a = 5;
b = a++; // b = 5,因为++后置,先运算后进行+1
a = 5;
b = ++a; // b = 6,因为++前置,先加1,再进行运算
在C语言程序里,一共有三种程序结构:顺序结构、选择结构(分支结构)、循环结构
顺序结构:按照实物本身特性,必须一个接着一个来完成。
选择结构:到某个节点后,会根据一次判断结果来决定之后走哪一个分支。
循环结构:循环结构有一个循环体,循环体是一段代码。对于循环结构来说,关键在于根据判断的结果,来决定循环体执行多少次。
总结:对于顺序结构来说,不需判断,因为下一句指令就是你要执行的。对与循环与选择结构来说,都需要进行判断。然后根据判断结果来决定怎么办。
逻辑上有一种类型,叫bool类型(又写作boolean类型,中文叫布尔类型)。布尔类型只有两个值,真和假。
C语言中有以下一些判断运算符
== 等于
!= 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于
if (bool值)
// 如果bool值为真,则执行代码段1,否则执行代码段2
{
代码段1
}
else
{
代码段2
}
if (bool值1) // 如果bool值1为真,则执行代码段1
{ // 否则则判断bool值2是否为 真,若为真则执行代码段2
代码段1 // 否则直接执行代码段3
}
else if (bool值2) // 开头的if和结尾的else都只能有一个,但是中间的
{ // else if可以有好多个。
代码段2
}
else
{
代码段3
}
第二种:switch case
switch (变量) // 执行到这一句时,变量的值已经知道了
{ // switch case语句执行时,会用该变量的值一次与各个
case 常数1: // case后的常数去对比,试图找到第一个匹配项。
代码段1; // 找到匹配的项目后,就去执行该case对应的代码段
break; // 如果没找到则继续下一个case,直到default。
case 常数2: // 如果前面的case都未匹配,则default匹配。
代码段2;
break;
.....
default:
代码段n;
break;
}
注意:
1、case中必须是常数,而且必须是整形(不能是float double,可以是int char)
2、一般来说,每个case中代码段后都必须有一个break;如果没有,结果可能会让你大吃一惊
3、case之后一般都会有default。语法上允许没有default,但是建议写代码时一定要写。
4、调试方法:在不同分支或者需要自定打印一些数据然后运行后根据打印内容,来分析程序的实际走向和运行情况,一次来做调试分析。
switch case和if else对比:
1、if else适合对比条件比较复杂,但是分支比较少的情况;switch case适合那种对比条件
不复杂,但是分支数很多的情况。
2、所有的选择结构,其实都可以用if else来实现。但是只有部分才可以用switch case实现。
一般的做法是:在适合使用switch case的情况下会优先使用switch case,如果不适合使用
switch case,则不得不使用if else。
for (循环控制变量初始化; 循环终止条件; 循环控制变量增量)
{
循环体
}
注意:
1、for循环中()中三部分可不可以省略?
标准的for循环,应该把循环控制变量的初始化,增量都放在()当中,并且在循环体中绝对不应该更改循环控制变量(可以引用它的值,但不应该改变它)。
2、死循环 for(;
5.2.2、while循环
i = 1;
sum = 0; // 循环初始化
while (i < 100) // 终止条件
{
printf("i = %d.\n", i);
sum += i; // 循环体
i += 2; // 循环控制增量,属于循环体的一部分
}
while循环的执行步骤:
0、首先是循环初始化。这一部分其实不属于while循环本身。
1、先判断终止条件是否满足。如果是真,则进入第2步;否则直接退出。
2、执行循环体,然后转入第1步。
i = 1;
sum = 0; // 初始化条件
do
{
printf("i = %d.\n", i);
sum += i;
i += 2; // 增量,循环体的一部分
}while (i < 100); // 终止条件
do while循环的执行步骤:
0、首先是循环初始化。这一部分其实不属于do while循环本身。
1、执行循环体(循环控制变量的增量是循环体的一部分)
2、判断终止条件。若成立,则转入1;若不成立则退出
总结:不管哪种循环结构,都不能缺少一些要素:
循环控制条件初始化,终止条件,循环控制变量增量,循环体。
不同的循环方式(for和while和do while)都有这些,只是格式不同,表现形式不同,放的地方不同,可读性不同,看起来和设计起来难度不同。
while循环和do while循环哪里不同?while循环是先判断后执行,do while循环是先执行后判断,等循环开始转了之后,其实是一样的。
基础知识:
当我们定义了一个局部变量,但是没有初始化的时候,这个值是随机的。
当我们定义了一个全局变量,但是没有初始化的时候,这个值是零。
理解和记忆是相互促进的。如果看不懂,就去记,记住了自然就明白了。如果记不住,就去理解,理解了自然就记住了。
1、给三个数,打印出其中最大的数
if(a>b && a>c)
a
else if(b>c)
b
else
c
2、规则:90分及以上为优,80分及以上为良,60分及以上为及格,以下为不及格,然后输入一个学生分数,然后printf打印“you” “liang” “jige” “bujige”
if (a>=90)
you
else if(a>=80)
liang
else if(a>=60)
jige
else
bujige
3、计算100以内所有奇数的和
for(i=1,sum=0;i<=100;i++)
if (i%2!=0)
// sum = sum + i; // 新手写法
sum += i;
printf(sum)
4、算一下10!(10987····1)
for(i=10,ans=0;i>0;i--)
// ans = ans*i; // 新手写法
ans *= i;
printf("i=%d.",i) //使用printf进行调试
5、打印一张ASCII码表(提示:数字用%d,字符用%c打印)
for(i=0;i<128;i++)
printf("%d,%c\n",i,i);
截至目前为止,已经学习的数据类型,运算符,三种程序结构,已经可以完成一些C语言程序了。但是不足之处在于写简单程序可以,写不了复杂程序。
当程序简单的时候,一个人可以用一个main函数搞定功能。当程序变成的时候,超出了人的大脑承受范围,这时候逻辑不清了。这时候就需要把一个大程序分成许多小的模块来组织,于是乎出现了概念叫做函数。
函数是C语言代码的基本组成部分,它是一个小的模块,整个程序由很多个功能独立的模块(函数)组成。这就是程序设计的基本分化方法。
函数定义:函数定义是关键,是这个函数的实现。函数定义中包含了函数体,函数体中的代码段决定了这个函数的功能。
函数声明:函数声明实际上是叫函数原型声明。什么叫原型?函数的原型包含三部分:函数名,返回值类型,函数参数列表。通俗讲,函数原型就是这个函数叫什么,接收什么类型的几个参数,返回一个什么样的返回值。
函数声明的作用,在于告诉使用函数的人,这个函数使用时应该传递给他什么样的参数,它会返回什么样类型的返回值。这些东西都是写函数的人在函数定义中规定好的,如果使用函数的人不参照这个原型来使用,就会出错,结果就会和你想的不一样。
函数调用:函数调用就是使用函数名来调用函数完成功能。调用时必须参照原型给函数传参,然后从函数得到适当的返回值作为结果。
形参:形式参数的简称。在函数定义和函数声明中的参数列表中的参数,都是形参。
实参:实际参数的简称。函数调用中,实际传递的参数才是实参。
函数调用的过程,其实就是实参传递给形参的一个过程。这个传递实际是一次拷贝。实际参数的时候,实参(本质是一个变量)本身并没有进入到函数内,而是把自己的值复制了一份传给了函数中的形参,在函数中参与运算。这种传参方法,就叫做传值调用。
当函数执行完之后,会给调用该函数的地方返回一个值。这个值的类型就是函数声明中返回值类型,这个值就是函数体中最后一句return xxx;返回的那个值。
第一点:起名字时候不能随意,要遵守规则。这个规则有两个层次:第一层就是合法,第二层是合理。合法就是符号C语言中变量名的命名规则。合理就是变量名起的好,人一看就知道什么意思,一看就知道这个函数是干嘛的,而且优美、好记。
第二点:C语言中,所有的符号都是区分大小写的。也就是说abc和Abc和aBc都是不同的符号。
第三点:C语言函数名变量名的命名习惯。没有固定的结论,有多种使用都很广泛的命名方式。介绍两种这里,
一种是linux的命名习惯(单词用下划线分隔)
student_age str_to_int
另一种是骆驼命名法 (驼峰命名法)
studentAge StrToInt
hisilicon海思半导体 HI_xxxx
1、自学(网上去搜)C语言中函数名和变量名的命名规则。
2、自学命名习惯
3、自学程序风格。空格 空行 缩进····
《高质量程序设计指南》 作者:林锐
华为代码规范
到目前为止,我们已经学习了C语言的基本数据类型:整形、浮点型、字符型。再往后
就是复合数据类型。
所谓复合数据类型,是指由简单数据类型,经过一定的数据结构封装,组成而成的新的
数据类型。譬如数组、譬如结构体、譬如共用体
数组就是数组成一个组,数就是一个特定数据类型的变量,组就是说好多数放在了一起。
int a[4];
// 数组中元素类型 数组名[数组元素个数];
总结:数组中的所有元素必须是同一种数据类型,不可能在一个数组中存储两种数据类型的数。
数组定义的时候作为整体定义。但是使用的时候不能作为整体使用,使用时必须拆开使用数组中的各个元素。
譬如数组int a[4],使用其中的四个元素,分别用a[0]``a[3],其中[]是数组的标志,[]中的数字叫做数组下标(index,索引),下标是我们访问数组中各个元素的指引。下标是0代表数组中第一个元素,下标是1代表数组第二个元素。如果数组长度为n,下标中最后一个是n-1。访问数组时要特别注意下标,下标是从0开始的,如果下标超出了n-1,会产生越界访问,结果是不可预期的。
初始化(initialize,简写为init),是为了让对象有一个预定的初始状态。
譬如说:
(1) 简单变量的初始化
当一个局部变量定义时没有初始化,它的值是随机的。这个如果没有注意,可能会导致程序出错。怎么办?解决方案有两个:
第一个,在定义过后明确给它赋值,使用=运算符。
第二个,定义该变量时,同时进行初始化。
总结:
1、一般来讲,只要你记得显示赋值,则两种方式并无优劣差异。但是人会犯错,会不小心,所以还是定义同时初始化好一点,因为这个定义的时候就有了固定值,即使之后忘记显示赋值也不会造成结果是随机的。
2、一般情况下,定义的同时都将变量初始化为0。局部变量定义同时初始化为0,这是一个写代码好习惯。
(2)数组的初始化
第一种:完全初始化。依次赋值
第二种:不完全初始化。初始化式中的值从a[0]开始,依次向后赋值,不足的默认用0填充赋值
int a[5] = {[1]=100,[4]=99}; //中间的a[1-3]初始化为零
int a[5]; // 整形数组
float a[5]; // 浮点型数组
double a[5]; // 双精度浮点型数组
char a[5]; // 字符数组
程序在环境中运行时,需要一定的资源支持。这些资源包括:CPU(运算能力)、内存等,这些资源一般由运行时环境(一般是操作系统)来提供,譬如我们在linux系统上./a.out运行程序时,linux系统为我们提供了运算能力和内存。
程序越庞大,运行时消耗的资源越多。譬如内存占用,越大的程序,占用的内存越多。占用内存的其中之一,就是我们在程序中定义的变量。
C语言程序中,变量的实质就是内存中的一个格子。当我们定义(创造一个变量)了一个变量后,就相当于在内存中得到了一个格子,这个格子的名字就是变量名,以后访问这个内存格子就使用该变量名就行了。这就是变量的本质。
数据类型的实质是内存中格子的不同种类。譬如在32位机器上:
短整形格子(short) 占用2字节空间 16位
整形格子(类型是int) 占用4字节空间 32位
单精度浮点型格子(float) 占用4字节空间
双精度浮点型格子(double) 占用8字节空间 64位
字符型格子(char) 占用1字节空间 8位
二进制:
二进制位:
字节:等于8个二进制位
作用:返回一个变量或者一个数据类型的内存占用长度,以字节为单位。
sizeof(a)/sizeof(a[0]) 测试一个数组中究竟有多少个元素
int main(int argc, char **argv)
{
char a[5] = {'a','b','c','d','e'};
// char a[5] = {97,98,99,100,101};
for(i=0;i<5;i++)
{
printf("a[%d] = %d %c.\n",a[i],a[i])
}
return 0;
}
基础知识:
1、在C语言中引用一个单个字符时,应该用单引号’‘括起来,譬如’a’。
2、定义数组同时初始化,则可以省略数组定义时[]中的长度。C语言编译器会自动推论其长度,推论依据是初始化式中初始化元素的个数。由此可知,省略[]中数组元素个数只有一种情况,那就是后面的初始化式必须为完全初始化。
3、在C语言中引用一个字符串时,应该用"“括起来,譬如"abcde”
"abcde"实际上有6个字符,分别是’a’ ‘b’ ‘c’ ‘d’ ‘e’ '\0’
’\0’ 这个字符是ASCII码表中的第一个字符,它的编码值是0,对应的字符是空字符(不可见字符,在屏幕上看不见,没法显示,一般要用转义字符方式来显示。譬如’\n’表示回车符,’\t’表示Tab,’\0’代表空字符)
‘\0’是C语言中定义的字符串的结尾标志。所以,当c语言程序中用"abcde"这种方式去初始化时,编译器会自动在字符’e’后面添加一个’\0’。于是乎变成了6个字符。
指针全称是指针变量,其实质是C语言的一种变量。这种变量比较特殊,通常它的值会被
赋值为某个变量的地址值(p = &a),然后我们可以使用*p这样的方式去间接访问p所
指向的那个变量。
指针存在的目的就是间接访问。有了指针之后,我们访问变量a不必只通过a这个变量名来
访问。而可以通过p = &a; *p = xxx;这样的方式来间接访问变量a。
&:取地址运算符,将它加在某个变量前面,则组合后的符号代表这个变量的地址值。
例如: int a; int *p; p = &a; 则将变量a的地址值赋值给p。
就在上面的例子中,有以下一些符号:
a 代表变量a本身
p 代表指针变量p本身
&a 代表变量a的地址值
*p 代表指针变量p所指向的那个变量,也就是变量a
&p 代表指针变量p本身的地址值。符号合法,但对题目无意义
*a 把a看作一个指针,*a表示这个指针所指向的变量。该符号不合法
:指针符号(指针运算符)。指针符号在指针定义和指针操作的时候,解析方法是不同的。
int p; 定义指针变量p,这里的p含义不是代表指针变量p所指向的那个变量,在定义时这里的含义是告诉编译器p是一个指针。
int p; // p是一个整形变量
int *p; // p是一个指针变量,该指针指向一个整形数
使用指针的时候,*p则代表指针变量p所指向的那个变量。
指针既然是一种变量,那么肯定也可以定义,也可以初始化
第一种:先定义再赋值
int *p; // 定义指针变量p
p = &a; // 给p赋值
第二种:定义的同时初始化
int *p = &a; // 效果等同于上面的两句
指针变量本质上是一个变量,指针变量的类型属于指针类型。int *p;定义了一个指针类型的变量p,这个p所指向的那个变量是int型。
int * pInt; // pInt是指针变量,指向的变量是int类型
char *pChar; // pChar是指针类型,指向的变量是char类型
float *pFloat;
double *pDouble;
各种指针类型和它们所指向的变量类型必须匹配,否则结果不可预知。
int p;
第一种:首先看到p,这个是变量名;其次,p前面有个,说明这个变量p是一个指针变量;最后,*p前面有一个int,说明这个指针变量p所指向的是一个int型数据。
char ((*pfunc)[])(char *, char *) 类似的复杂表达式,可以用相同的分析方法得到
第二种:首先看到p,这个是变量名;其次,看到p前面的int *,把int *作为一个整体来理解,
int *是一种类型(复合类型),该类型表示一种指向int型数据的指针。
总结:第二种方法便于理解,但是不够本质;建议用第一种方法来理解,因为这种思维过程可以帮我们理解更复杂的表达式。
数组名:做右值时,数组名表示数组的首元素首地址,因此可以直接赋值给指针。
如果有 int a[5];
则 a和&a[0]都表示数组首元素a[0]的首地址。
而&a则表示数组的首地址。 【待解析…】
int main()
{
int a[5] = {555,444,333,222,111};
int *p;
p = &a; // 编译报警告,但是执行结果是对的,打印555
p = &a[0]; // 相当于 p = &(a[0]);编译没错,执行也没错,打印555
p = a; // 编译没错误没警告,执行也没错,打印555
}
注意:数组首元素的首地址和数组的首地址是不同的。前者是数组元素的地址,而后者是数组整体的地址。两个东西的含义不同,但是数值上是相同的。
根据以上,我们知道可以用一个指针指向数组的第一个元素,这样就可以用间接访问的方式去逐个访问数组中各个元素。这样访问数组就有了两种方式。
有 int a[5]; int *p; p = a;
数组的方式依次访问:a[0] a[1] a[2] a[3] a[4]
指针的方式依次访问:*p *(p+1) *(p+2) *(p+3) *(p+4)
指针本身也是一种变量,因此也可以进行运算。但是因为指针变量本身存的是某个其他变量的地址值,因此该值进行* / %等运算是无意义的。两个指针变量相加本身也无意义,相减有意义。指针变量+1,-1是有意义的。+1就代表指针所指向的格子向后挪一格,-1代表指针所指向的格子向前挪一格。
p++就相当于(p++),p先与++结合,然后p++整体再与结合。
p++解析:++先跟p结合,但是因为++后置的时候,本身含义就是先运算后增加1(运算指的是p++整体与前面的进行运算;增加1指的是p+1),所以实际上p++符号整体对外表现的值是p的值,运算完成后p再加1.
所以p++等同于:*p; p += 1; //555
*++p等同于 p += 1; *p; //444
(p)++,使用()强制将与p结合,只能先计算p,然后对p整体的值++。//555
++(p),先p取值,再前置++,该值+1后作为整个表达式的值。// 556
总结:++符号和指针结合,总共有以上4种情况。–与++的情况很类似。
int add(int a, int b) 函数传参使用了int型数,本身是数值类型。实际调用该函数时,实参将自己拷贝一份,并将拷贝传递给形参进行运算。实参自己实际是不参与的。
所以,在函数中,是没法改变实参本身的。
例子:数值交换
/* 学生类型结构体,保存一个学生的所有信息:姓名 学号 性别 */
struct Student
{
char name[20]; // 学生姓名
unsigned int num; // 学号
int isMale; // 性别
}
int main(void)
{
struct Student s1;
// 给结构体变量赋值
s1.name[0] = 'J';
s1.name[1] = 'i';
s1.name[2] = 'm';
s1.name[3] = '\0';
s1.num = 123;
s1.isMale = 1;
// 打印检验看对不对
printf("s1.name = %s, s1.num = %d, s1.isMale = %d",s1.name,s1.num,s1.isMale);
}
结构体是一个集合,集合中包含很多个元素,这些元素的数据类型可以相同,也可以不相同。所以结构体是一种数据封装的方法。结构体存在的意义就在于,把很多数据类型不相同的变量封装在一起,组成一个大的新的数据类型。
数据结构:把庞大复杂的数据用一定的方式组织管理起来,便于操作(查找,增加,删除等)这就叫数据结构。
结构体变量和普通变量一样,作为局部变量时,如果定义的时候无初始化也无显式赋值,则结构体变量中的子元素的值是随机的。
发现2种C语言接受的结构体初始化方式。
第一种,完全初始化。struct XX XX = {xx, xx, xx, xx, xx};
struct MyStudent s = {100,'d',12.445,111.11111};
printf("s.c = %c, s.d = %lf",s.c,s.d);
// 注意用,进行初始化,不能用分号
第二种,部分初始化。
{
x.a = xx,
x.b = xx,
x.c = xx,
x.d = xx, // 最后一个逗号可有可无
}; // 最后的分号不能遗漏
新增关键字: struct
新增操作符: . 成员访问运算符
#include
#include
union Data
{
int i;
float f;
char str[20];
};
int main( )
{
union Data data;
data.i = 10;
data.f = 220.5;
strcpy( data.str, "C Programming");
printf( "data.i : %d\n", data.i);
printf( "data.f : %f\n", data.f);
printf( "data.str : %s\n", data.str);
return 0;
}
/* 结果
data.i : 1917853763
data.f : 4122360580327794860452759994368.000000
data.str : C Programming
在这里,我们可以看到共用体的 i 和 f 成员的值有损坏,因为最后赋给变量的值占用了内存位置,这也是 str 成员能够完好输出的原因。现在让我们再来看一个相同的实例,这次我们在同一时间只使用一个变量,这也演示了使用共用体的主要目的:
*/
struct Male
{
int age;
char name[20];
int basketball;
};
struct Female
{
int age;
char name[20];
int aerobics;
};
union student
{
struct Male m;
struct Female f;
};
int main()
{
union student s[30];
s[0].m.basketball = 47;
s[1].f.aerobics = 48;
}
char -128 ~ 127
int -xxxx ~ + xxxx
新增关键字:union
// 定义一个枚举类型,限制了取值范围
#define SUN 0;
#define MON 1;
...
enum week
{
SUN,
MON,
TUE,
WED,
THU,
FRI,
SAT,
};
int main(void)
{
enum week today;
today = SAT;
switch(today)
{
case MON:
printf;
break;
case TUE:
printf;
break;
...
default:
printf;
break;
}
}
#define N 321 //宏定义的格式
宏定义要注意的问题:
1、宏定义一般是在函数的外面
2、宏定义必须要先定义,再使用宏。如果先使用就会编译报错。
3、宏定义中宏名一般用大写。不是语法规定的,是一般约定俗成的。
为什么使用宏定义?
在C语言中,一般使用常数的时候,都不是直接使用,而是先把该常数定义为一个宏,然后在程序中使用该宏名。
这样做的好处是,等我们需要修改这个常数时,只需要在宏定义处修改一次即可。而不用到代码中到处去寻找,看哪里都用过该常数。
注意:
宏定义后面的部分最好用括号括起来, 防止宏被替换时产生组合错误!
后面加U限制为无符号数,L限制为长整型
+ define N (321)
+ define SECS_PER_YEAR (365*24*60*60)U
C语言基础大模块:
数据类型
运算符
三种程序结构
函数
数组
指针
结构体、公用体、枚举
基础知识 + 推断能力
学习 = 基础知识 + 合理推论