目录
1>字符型:特殊的整型,占据 1 个字节(1byte---8bit)
3 关系运算符和关系运算表达式:> < == >= <= !=
1>在同一个作用域内,不能出现相同的标识符,同一个作用域内,不能重复定义变量名。
3>局部变量:就是在函数作用域或者是语句块作用域中定义的变量 全局变量:就是在文件作用域中定义的变量(实际开发中尽量不要使用全局变量)
4>全局变量和函数都属于文件作用域内的标识符,文件作用域内的标识符是可以通过 extern 扩展作用域的
1>并非所有的变量都可以声明为 static,形式参数不能声明为 static,只能声明 为 auto.
3>全局标识符如果用 static 修饰,并不是表示在全局区而是表示该标识符只能在本文件内被扩展使用。
一 初识C语言
1 main 主函数
2 注释
3 C 程序执行的过程:
4 C 程序的结构
5 进制的转换
1.内存容量
1TB--->1024GB1GB--->1024MB1MB--->1024KB1KB--->1024B byte(字节)1byte--->8bit(位)
2.二进制与十进制的转换
1>将二进制数转换成十进制
2>将十进制转换成二进制数
除以 2 逆向取余法:
22(10)=10110(2)
3.二进制与八进制的转换
1>将八进制数转换成二进制:
每 1 个八进制位转换成 3 个二进制位,左边不足三个的则补 0。
5 6 7 ---> 101 110 1112 3 4 ---> 010 011 100
2>将二进制数转换成八进制:
011 010 111 100 110 ---> 3 2 7 4 6011 010 111 101 110--->32756011 101 110 101 011--->35653
4.二进制与十六进制的转换
1>将十六进制数转换成二进制:
0----00001----00012----00103----00114----01005----01016----01107----01118----10009----1001A----1010 10B----1011 11C----1100 12D----1101 13E----1110 14F----1111 151 2 8 9 A D F ---> 0001 0010 1000 1001 1010 1101 1111
2>将二进制数转换成十六进制:
1110 1101 1111 1001 1110 ---> E D F 9 E
6 原码、反码、补码
数据在计算机里面都是以补码的形式存储。
原码 反码 补码37:0010 0101--->0010 0101--->0010 0101-37:1010 0101--->1101 1010--->1101 1011
二 数据类型、变量、常量
1 数据类型
C 语言的数据类型分为:基本类型和构造类型两种。
1.基本类型
1>字符型:特殊的整型,占据 1 个字节(1byte---8bit)
有符号字符型 signed char/char:有符号位取值范围:1000 0000( -128 ) ----0111 1111( 127 )无符号字符型 unsigned char:没有符号位,都是数值位取值范围:0000 0000( 0 )---1111 1111( 255 )
2>整型:整数类型
有符号的整型 signed int/int , 占据 4byte1000 0000 0000 0000 0000 0000 0000 0000( -2147483648 )---0111 1111 1111 1111 1111 1111 1111 1111( 2147483647 )无符号的整型 unsigned int , 占据 4byte0000 0000 0000 0000 0000 0000 0000 0000( 0 )---1111 1111 1111 1111 1111 1111 1111 1111 ( 4294967295 )短整型 short int:占据 2byte1000 0000 0000 0000( -32768 )---0111 1111 1111 1111( 32767 )无符号短整型 unsigned short int: 占据 2byte0000 0000 0000 0000( 0 )---1111 1111 1111 1111( 65535 )长整型 long long int: 占据 8byte( -9223372036854775808--9223372036854775807 )无符号长整型 unsigned long long int: 占据 8byte( 0--18446744073709551615)
3>实型:小数,浮点型,没有无符号的浮点型数据
float : 单精度浮点型,占据 4bytedouble : 双精度浮点型,占据 8bytelong double : 长双精度浮点型,占据 8byte 或者 16byte
2.构造类型
2 变量
类型名 变量名 = 初值 , 变量名 = 初值 ;char a , b , c ;int e ;char a = 0 , b = 0 , c = 0 ;char a = 0 ;unsigned char e = 0 ;int height = 170 ;int weight = 0 ;int a = 0 ;//在变量定义时,给变量赋值叫赋初值a = 0 ;//不是赋初值,这叫赋值
注意:
3 常量
1.整型常量
int a = 100; //100 是整型常量,占用 4byteunsigned int a = 200U; //200 是一个无符号的整型常量long int a = 200L; //200 是一个 long int 型常量long long int a = 200LL; //200 是一个 long long int 型常量,占据 8bytefloat f = 3.14f; //3.14 是一个单精度浮点型常量double d = 3.14; //3.14 是一个双精度浮点型常量long double ld = 3.14L; //3.14 是一个长双精度浮点型常量
2.十进制常量、八进制常量、十六进制常量的表示
char a = 11; //11 是十进制常量char b= 0 11; //11 是八进制常量,以数字 0 开头表示的是八进制char c= 0x 11; //11 是十六进制常量,以 0x 开头表示的是十六进制
3.转义字符常量:
4.常变量:用 const 修饰的标识符
const int a = 45;a = 100;// 错误,不能修改 a 的值
三 运算符与表达式
1 运算符与表达式
1.优先级与结合性
2 算术运算符和算术运算表达式
1. + - * / %
2.自增++ 自减--
1> ++后缀:先读后写
int main(void)
{
int a = 0;
a = 20;
a++;//相当于 a = a + 1; 21
printf("%d\n", a++);//先读后写,先把 a 的值(21)读出来,再 a = a + 1;
printf("%d\n", a);//22
}
printf("%d\n", a++);
//相当于
//printf("%d\n", a);
//a = a + 1;
2> ++前缀:先写后读
int main(void)
{
int a = 0;
a = 20;
++a;//相当于 a = a + 1; a = 21
printf("%d\n", ++a);//先写后读,先 a = a + 1;再把 a 的值(22)读出来
printf("%d\n", a);//22
}
printf("%d\n", ++a);
//相当于
//a = a + 1;
//printf("%d\n", a);
3 关系运算符和关系运算表达式:> < == >= <= !=
int a = 15;int b = 10;a > b //1a < b //0a < 15 //0a > 15 //0a >= 15 //1a == 15 //1a == b //0a != b //1
4 逻辑运算符和逻辑运算表达式
1.&&逻辑与运算符:
int a = 15;int b = 10;a > b && a < b//0a > b && a != b//1a && b//1
2.||逻辑或运算符:
int a = 15;int b = 10;a > b || a < b //1 a>b为真,有真则为真a > b || a != b //1a < b || a == b //0 两边都为假,则为假a || b //1 运算对象不为0,为真
3.!逻辑非运算符:
int a = 15;int b = 10;!(a > b) //0 a>b为真!(a < b) //1 a<b为假!a //0 a为真
5 赋值运算符和赋值运算表达式:
变量 = 表达式 ;a = 45;
复合的赋值运算符: += -= *= /= %=
int a = 15;a += 10; //a = a + 10; a = 25;a -= 10; //a = a - 10; a = 15;a *= 2; //a = a*2; a = 30;a /= 2; //a = a/2; a = 15;a %= 6; //a = a % 6; a = 3;a++; // 相当于 a += 1;a / = 10; // 错误 ,不能有 空格
6 逗号运算符和逗号运算表达式:,
int main(void)
{
int a = 0;
int b = 0;
int c = 0;
a = 5;
b = 15;
c = 10;
printf("%d\n", (++a, ++b, c++));//10
printf("%d\n",a);//6
printf("%d\n", b);//16
}
7 sizeof 求字节运算符
sizeof(表达式) 结果为表达式的数据类型占据的字节数
int a = 10;sizeof( int ) //4sizeof(unsigned int) //4sizeof(a) //4sizeof(165) //4sizeof(a + 10) //4sizeof(float) //4sizeof(double) //8sizeof(long double) //8
8 强制类型转换运算符:(类型名)(表达式)
int main(void){float a = 0;int b = 0;int c = 0;float d = 0;a = 7.5;b = 2;d = 1.5;c = a * b;//c = 15.000 000 000 000 000;printf("%d\n", c);//15c = (int)a * b;//c = 7*2;printf("%d\n", c);//14c = (int)(a * b) ;//c = 15;printf("%d\n", c);//15c = a*b*d;//c = 22.5; c = 22printf("%d\n", c);//22c = (int) a *b*d;printf("%d\n", c);//21c = (int)a *b* (int)d ;printf("%d\n", c);//14}
9 不同类型的数据混合运算
为了保证运算的精度,计算机会自动转向精度高的数据类型进行转换
char b = 0;float c = 0;char d = 'M';b = 'A'+ 32; //b = 65+32;c = 7 / 2.0f; //c = 3.500 000 000 000 000;
四 输入与输出函数、选择结构
1 数据的输出和输入
2 输出函数
C 语言中,最常用的输出函数时 printf 函数,用来在终端设备上按照指定格式进行输出。
1.printf 函数的调用形式:
2.printf 函数的使用方法:
1>使用方法 1:输出单个数据--不换行
说明:
格式字符
| 输出说明 |
c
|
输出一个字符
|
d 或 i
|
输出带符号的十进制整型数据,若为长整型用%ld ,短整型 %hd
|
o
|
以八进制格式输出整型数据,若以%#o,则在实际八进制数前加
了先导 0
|
x 或 X
|
以十六进制格式输出整型数据,若以%#x,则在实际十六进制数前
加了先导 0x,格式字符的大小写决定了十六进制数中的大小写
|
f
|
以带小数点的数学形式输出浮点型数据(单精度和双精度)
|
e 或 E
|
以指数形式输出浮点型数据
|
s
|
输出一个字符串,直到遇到’\0’结束
|
%
|
%%,实际输出的是一个%
|
2>使用方法 2:有数据需要原样输出的
int a = 100;printf("a = %d",a); //输出的结果是: a = 100 ,输出结果不换行
3>使用方法 3:同时输出多个数据
int a = 110;char c = 'a';//调用一次 printf 函数,就能输出这两个变量的值printf("%d%c\n",a,c);printf("a = %d c= %c\n",a,c);printf("a = %d,c= %c\n",a,c);
3.输出数据所占宽度说明
在做数据输出操作时,有的时候需要规定输出数据的宽度。
1>整型数据的输出宽度
int a = 250;int b = 20;要求输出的两行结果右对齐。
分析:
a 的数值有 3 位,b 的数值有 2 位
b 的数据前应该补一位空格 ,此时就要设定输出 b 的数据的宽度,输出的宽度应该为 3
printf("%d",a);
printf(" %3d ",b);
int a = 1234; printf("%6d\n",a); printf("%4d\n",a); printf("%3d\n",a); printf("%2d\n",a);
总结:
printf(“% m d”,a);
2>浮点型数据的输出宽度说明
float a = 3.14159; printf("%7.4f\n",a); printf("%6.6f\n",a); printf("%6.6f\n",a); printf("%0.3f\n",a);
4.输出的数据左对齐
double a = 3.141592653;double b = 3.14;printf("% - 10.7f,%f\n",a,b);// 输出结果 :3.1415927 ,3.140000//3.1415927 后面有一个空格
3 输入函数
scanf(格式控制,地址列表);int a = 0;scanf("%d",&a);char a = 0;scanf("%c",&a);//a = 'M';
1>scanf 函数中的地址列表应当是变量地址,不能是变量名。
scanf("%d",a);//错误,缺少 &
scanf("a=%d,b=%d",&a,&b);要输入 :a=123,b=456输入时 a= , b= 也要在对应的位置手动输入
scanf("%c%c",&a,&b);如果输入 :M N则 a 为 'M',b 为空格字符必须是输入 :MNb 的值才是 'N'
scanf("%d%d",&a,&b);输入时 :123 456输入 123 后加空格表示 123 输入完成并赋值给 a
4 算法的基本结构
4.1 顺序结构:
复合语句:
由大括号{}中的 0 个或多个声明和语句列表共同构成。
int main(void)
{
int a = 0;
int b = 0;
a = 5;
b = 4;
{
int a = 6;//变量声明
printf("%d\n",a);//这个 a 的值是 6,和前面的 a 不是同一个
a++;//自增表达式语句
printf("%d\n",a);//函数调用语句
++b;
}
printf("%d\n", a);//这个 a 的值是 5
printf("%d\n",b);
return 0;
}
注意:1>复合语句不以分号;作为结束符,即 最后的}后面不加分号 。2>在复合语句中 可以定义变量,但仅在复合语句中有效 ,即作用域是{}括起来的部分。int main(void) { int b = 0; b = 4; { int a = 6; printf("%d\n",a); a++; printf("%d\n",a); ++b; };//错误,不能加; printf("%d\n", a);//错误,a 没有定义 printf("%d\n",b); return 0; }
4.2 选择结构(分支结构)
1.if 语句
//输入 a 和 b 的值,判断并输出最大值
int main(void)
int main(void)
{
int a = 0;
int b = 0;
int max = 0;
printf("请依次输入 a 和 b 的值:");
scanf("%d%d",&a,&b);
max = a;
if(max < b)
max = b;
printf("max:%d\n",max);
return 0;
}
if 条件语句中的 语句 1 不是只有一条语句的意思,可以是多条语句用 {} 括起来的复合语句。int main(void) { int a = 0; int b = 0; int max = 0; printf("请依次输入 a 和 b 的值:"); scanf("%d%d",&a,&b); max = a; if(max < b) { max = b; printf("a < b \n"); } printf("max:%d\n",max); return 0; }
2.if...else 语句
//输入 a 和 b 的值,判断并输出最大值
int main(void)
{
int a = 0;
int b = 0;
int max = 0;
printf("请依次输入 a 和 b 的值:");
scanf("%d%d",&a,&b);
if(a < b)
max = b;
else
max = a;
printf("max:%d\n",max);
return 0;
}
3.if...else if 语句
//输入成绩分数,并判断该成绩属于哪个等级
int main(void)
{
int score = 0;
printf("请输入成绩:");
scanf("%d",&score);
if (score >= 0 && score <= 100)
{
if(score >= 90)
printf("A+\n");
else if(score >= 80)
printf("A\n");
else if(score >= 70)
printf("B+\n");
else if(score >= 60)
printf("B\n");
else
printf("不合格\n");
}
else
printf("请输入合法的成绩!");
return 0;
}
4.if 语句嵌套
1 修改下面的程序使程序:输入 a 和 b 的值,判断最大值是否大于 100,是则输出最大值。
int main(void) { int a = 0; int b = 0; printf("请依次输入 a 和 b 的值:"); scanf("%d%d",&a,&b); if(a < b) if(b > 100) printf("max:%d\n",b); else if(a > 100) printf("max:%d\n",a); return 0; }
注意:C 语言规定,else 总是与它前面最近的为配对的 if 配对。
//所以修改后应为: int main(void) { int a = 0; int b = 0; printf("请依次输入 a 和 b 的值:"); scanf("%d%d",&a,&b); if(a < b) { if(b > 100) printf("max:%d\n",b); } else { if(a > 100) printf("max:%d\n",a); } return 0; }
2 输入 a 、 b 、 c 的值,判断并输出最大值int main(void) { int a = 0; int b = 0; int c = 0; int max = 0; printf("请依次输入 a、b、c 的值:"); scanf("%d%d%d", &a, &b,&c);// if (a > b) { if (a > c) max = a; else max = c; } else//b > a { if (b > c) max = b; else max = c; } printf("max:%d\n", max); return 0; }
5.switch 多路分支语句
输入数字 1-7 ,并输出显示对应的星期int main(void) { int week = 0; printf("今天星期几:"); scanf("%d", &week);//1---'1' switch (week)//week 是表达式 { case 1:printf("今天是星期一\n"); break; case 2:printf("今天是星期二\n"); break; case 3:printf("今天是星期三\n"); break; case 4:printf("今天是星期四\n"); break; case 5:printf("今天是星期五\n"); break; case 6:printf("今天是星期六\n"); break; case 7:printf("今天是星期天\n"); break; default:printf("输入数据有误!\n"); } return 0; }
注意:1>switch 后面括号中的表达式可以是 整型、字符型和枚举型 。2> 在 case 后的各常量表达式的值 不能相同3> 在 case 后,允许有多个语句,可以不用 {} 括起来,而整个 switch 结构一定要有一对{}4> 各 case 和 default 语句的先后 顺序可以改变 ,不影响程序执行结果。
6.条件运算符和条件运算表达式: (?:)
//输入 a、b 的值,判断并输出最大值,使用条件表达式。int main(void) { int a = 0; int b = 0; int max = 0; printf("请依次输入 a 和 b 的值:"); scanf("%d%d",&a,&b); max = a>b?a:b; printf("max:%d\n",max); return 0; }
五 循环结构
1 循环结构语句
1.while 语句
1. 输出 1---n 之间的数int main(void) { int i = 1; int n = 0; printf("请输入 n 的值:"); scanf("%d",&n);//10 15 while(i <= n) { printf("%d\n",i); i++; } return 0; }
2. 计算 m+...+n 的值int main(void) { int n = 0; int m = 0; int sum = 0; printf("请依次输入 m 和 n 的值:"); scanf("%d%d",&m,&n);//m+...n 10 15 while (m <= n) { sum = sum + m; m++; } printf("sum=%d\n", sum); return 0; }
2.do...while 语句
1计算 m+...+n 的值,使用 do while 语句。
int main(void) { int n = 0; int m = 0; int sum = 0; printf("请依次输入 m 和 n 的值:"); scanf("%d%d",&m,&n);//m+...n 10 15 do { sum = sum + m; m++; }while (m <= n); printf("sum=%d\n", sum); return 0; }
2输出 1---n 之间的数,使用 do while 语句int main(void) { int i = 1; int n = 0; printf("请输入 n 的值:"); scanf("%d",&n);//10 15 do { printf("%d\n",i); i++; }while(i <= n); return 0; }
while 语句和 do...while 语句的区别 :while 语句是先判断后执行,do...while 语句是先执行,至少会执行一次。
3.for 语句
1.while 语句与 for 语句的替换:计算 1+2+3+...+n 的值
使用 while 语句实现 :int i = 1; while(i <= n) { sum = sum + i; i++; }
使用 for 语句实现 :int i = 1; for(i = 1;i <= n;i++) { sum = sum + i; }
2. 输出 1---n 之间的数,使用 for 语句。int main(void) { int i = 1; int n = 0; printf("请输入 n 的值:"); scanf("%d",&n);//10 15 /*while(i <= n) { printf("%d\n",i); i++; }*/ for(i = 1;i <= n;i++) { printf("%d\n",i); } return 0; }
3.计算 m+...+n 的值,使用 for 语句。int main(void) { int n = 0; int m = 0; int sum = 0; printf("请依次输入 m 和 n 的值:"); scanf("%d%d",&m,&n);//m+...n 10 15 /*while (m <= n) { sum = sum + m; m++; }*/ for(;m <= n;m++) { sum = sum + m; } printf("sum=%d\n", sum); return 0; }
注意:1>for 语句的 三个表达式不是必须的 。2>当条件表达式 ( 表达式 2)的值为假(为 0)时 for 循环语句就结束 。3>可以在循环体内执行 break,continue,goto 语句。4> 表达式 2 是空 的,表明表达式 2 的值一直是真,即 死循环 。for(;;)//死循环语句{}相当于while(1){}小结:for(i=m;i < n;i++)//循环次数 :n-m 次for(i=m;i <= n;i++)//循环次数 :n-m+1 次
2 中断语句
1.break 语句
1 计算 m+...+n 的值,当累加的值大于 100 时退出循环int main(void) { int n = 0; int m = 0; int sum = 0; printf("请依次输入 m 和 n 的值:"); scanf("%d%d",&m,&n);//m+...n 10 50 for(;m <= n;m++) { sum = sum + m; if(sum > 100) break; } printf("sum=%d\n", sum); return 0; }
2 输出 1---n 之间的数 ,当输出的数大于 100 时结束循环
int main(void) { int i = 1; int n = 0; printf("请输入 n 的值:"); scanf("%d",&n);//10 15 for(i = 1;i <= n;i++) { printf("%d\n",i); if(i > 100) break; } return 0; }
2.continue 语句
int main(void)
{
int i = 1;
int n = 0;
int sum = 0;
printf("请输入 n 的值:");
scanf("%d", &n);//150
for (i = 1; i <= n; i++)
{
sum = sum + i;
printf("sum:%d\n",sum);
if (i > 100)
continue;
printf("i=%d\n", i);
}
return 0;
}
3.goto 语句(了解)
int main(void)
{
int i = 1;
int j = 0;
int k = 0;
for (j = 0; j < 2; j++)//2
{
for (i = 0; i < 15; i++)//15
{
if (i == 10)
goto again;
printf("i=%d\t", i);
}
}
again:printf("穿越啦\n");
return 0;
}
六 函数
1 函数的定义
返回值类型 函数名(形式参数 1, 形参 2, ...)// 函数头{}// 函数体
void printfStart(void)//打印一行星号
{
printf("************\n");
return;
}
void sel(int n)//n 表示输入的分数
{
if (n > 90)
printf("你的成绩属于优秀!");
else if (n > 80)
printf("你的成绩属于良好!");
else if (n > 70)
printf("你的成绩属于中等!");
else if (n > 60)
printf("你的成绩属于及格!");
else
printf("你的成绩属于不及格!");
}
2 函数的调用
3 函数的声明
4 函数的设计原则
1.一个函数实现一个功能
2.返回值的原则:如果计算有结果需要加返回值
3. 形参 的设计及原则:如果计算的过程需要有数值进行 辅助 , 则需要加参数。4.如果函数有形式参数则必须进行 参数检查 ,检查参数是否有 异常。通常用 分支结构 (选择结构)进行参数检查,如果有错误则返 回-15.函数体的设计思路第一步:定义变量第二步:逻辑关系运用,选择结构还是循环结构还是综合运用。
1.定义一个函数实现:求 n 以内的奇数累加和。主函数实现:输入 n 的值,调用该函数后, 输出对应的累加和。int sum(int n); int main(void) { int m = 0; int result = 0; printf("请输入一个整数:"); scanf("%d",&m); result = sum(m); if(result == 0) printf("形参异常!\n"); else printf("%d 以下的奇数的累加和是:%d\n",m,result); return 0; } //函数的功能:求奇数的累加和,1+3+5+...+n int sum(int n) { int i = 0; int s = 0; if(n<1)//形参的异常检查 return 0; //for(i=1;i<=n;i++) //{ // if(i%2 != 0)//if(i%2 == 1)//if(i%2) // s = s + i; //} for(i=1;i<=n;i+=2) { s = s + i; } return s; }
2.定义一个函数实现:计算 10 - 1/2 - 1/3 - ...- 1/n 的值。主函数实现:输入 n 的值, 调用该函数后,输出对应的结果。float sum_div(int n);//函数的声明 int main(void) { int m = 0; float s = 0; printf("请输入一个整数:"); scanf("%d",&m); s = sum_div(m); if(s == 0) printf("形参异常\n"); else printf("10-1/2-1/3-...-1/%d 的值:%f\n",m,s); return 0; } //函数要实现的功能:计算 10 - 1/2 - 1/3 - ...- 1/n 的值 float sum_div(int n) { int i = 0; float sum = 10; if(n<2)//判断形参是否异常 return 11; for(i=2;i<=n;i++) { sum -= 1.0/i; } return sum; }
3.定义一个函数实现:根据 x 求 y 的值。主函数实现:输入 y 的值,调用该函数后,输出对应的结果。
int y_value(int x);//函数的声明 int main(void) { int m = 0; int y = 0; printf("请输入一个整数:"); scanf("%d",&m); y = y_value(m); if(y == -1) printf("形参异常\n"); else printf("x:%d,y:%d\n",m,y); return 0; } //函数要实现的功能:求 y 的值 int y_value(int x) { int y = 0; if(x<1) y = 2*x;//return 2*x; else if(x>=1 && x<5) y = 3*x - 2;//return 3*x - 2; else if(x>=10) y = 4*x - 3;//return 4*x - 3; else//形参异常 y = -1;//return -1; return y; }
七 递归调用、作用域和存储类别
1 函数的递归调用
1>递归的概念
2>递归思想应该关注的几点:
1. 使用递归调用的形式编写函数实现求 :1+2+3+...+n#include <stdio.h> int sum(int m);//函数的声明 int main(void) { int n = 0 ,s = 0; printf("请输入 n 的值:"); scanf("%d",&n); s = sum(n);//函数的调用 printf("1+2+3+...+%d 的值为%d\n",n,s); return 0; } int sum(int m) { if(m<1)//形参异常检查 return -1; else if(m==1)//当形参为 1 时返回 1,即结束递归调用的条件 return 1; else return m+sum(m-1); }
2 作用域
1.作用域:一个代码空间
注意:1>在同一个作用域内,不能出现相同的标识符,同一个作用域内,不能重复定义变量名。
int foot(void) { int a = 0; } void foot(void)//错误,函数名不能相同 { char a = 0; } int main(void) { char a; char a;//错误,重复定义变量 a return 0; }
2>一个标识符不能同时属于两个作用域,使用就近原则
#include <stdio.h> char height = 10;//height 属于文件作用域 int main(void) { char height = 12;//height 属于函数作用域 printf("%d\n",height);//使用的是函数里面的 height,结果:12 return 0; }
3>局部变量:就是在函数作用域或者是语句块作用域中定义的变量 全局变量:就是在文件作用域中定义的变量(实际开发中尽量不要使用全局变量)
4>全局变量和函数都属于文件作用域内的标识符,文件作用域内的标识符是可以通过 extern 扩展作用域的
//指出下面程序的错误 int main(void) { foo();//error printf("%d", g_a);//error return 0; } void foo(void){} int g_a = 0; //改进如下 extern void foo(void); extern int g_a; int main(void) { foo();//error printf("%d", g_a);//error return 0; } void foo(void){} int g_a = 0;
3 存储类别
void foo(int a)
{
int b = 0;
}//a 内存销毁
int main(void)
{
foo(10);//a 内存开辟
return 0;
}
4 栈变量:auto 声明的变量
void foo(int a)
{
int b = 0;//b 开辟内存
{
int i = 0;//i 开辟内存
}//i 内存销毁
i = 10;//错误,i 内存已经销毁
}//b 内存销毁,a 内存销毁
int main(void)
{
foo(10);//a 开辟内存
foo(20);//a 重新开辟内存
return 0;
}
auto int a = 0;//错误,a 是全局变量不能用 auto 修饰
int main(void)
{
auto int i = 0;
int b = 0;
}
5 全局区变量:用 static 声明的变量
void foo(int a)
{
static int b = 0;//b 编译时开辟内存,该语句只在编译时执行一次,后面不再执行
{
int i = 0;//i 开辟内存
}//i 内存销毁
b++;
printf("%d\n",b);
}//a 内存销毁
int main(void)
{
foo(1);//a 开辟内存
foo(2);//a 重新开辟内存
return 0;//主函数结束时 b 销毁内存
}
注意:1>并非所有的变量都可以声明为 static,形式参数不能声明为 static,只能声明 为 auto.
void foo(static int a);//错误,形参 a 不能用 static 声明 void foo(auto int a);//正确
2>变量声明为 static 时,不赋初值时默认为 0.
void foo(void) { static int count;//默认是 0 count++; printf("%d", count); } int main(void) { foo(); foo(); foo(); return 0; }
3>全局标识符如果用 static 修饰,并不是表示在全局区而是表示该标识符只能在本文件内被扩展使用。
main.c: extern int g_a;//正确 static int g_a; fun.c extern int g_a;//错误
main.c: extern void foo(void);//正确 static void foo(void){}; fun.c extern void foo(void);//错误
八 指针与变量
1 指针的预备知识
int a = 0;
2 指针的基本概念和指针常量
1.什么是指针:
指针就是地址。
2.怎么获取变量的地址:
取地址符号 &
int a = 10;
printf("%d\n",a);//输出 a 的值
printf("%d\n", &a);//输出 a 的地址
3.C 语言中地址绑定一块内存
int 地址绑定 4bytedouble 绑定 8bytechar 绑定 1byte
4.指针(地址)常量的写法
int a = 0;
float f = 3.14f;
double d = 3.14;
char c = 'M';
&a;&f;&d;&c;//指针常量
4 = 100 ; //错误 ,常量 4 不能被修改&a = &b; //错误 ,&a 是指针常量不能修改
int a;
int b = 10;
a = b;//a = 10;
3 指针的类型
int a = 0;//那么&a 的类型名是 int *
double d = 0;//那么&d 的类型名是 double *
char c = 0;//那么&c 的类型名是 char *
long long int L = 0;//那么&L 的类型名 long long int *
*:指针运算符int * 绑定 4bytedouble * 绑定 4bytechar * 绑定 4byte
4 指针变量的定义
普通变量的定义:类型名 变量名 = 初始值;
int a = 0;
int * a;//int *是类型名,a 是指针变量
int * b = 10;//错误,10 是整型常量,不是地址常量
int c = 0;
int * d = &c;//正确
int e = 0,f = 0;
int * g = &e,h = 10,*i = &f;//指针变量 i 前面的*不能少,h 是 int 型变量
5 指针变量的基本用法
int a = 0;
int * b = &a;
*b = 100;//*b 是 a 的小名或别名,a 和*b 都标识同一块内存