- 目录:
- 一、 变量与常量
- 二、常用计算机单位、数据类型、字符串、常用转义字符、ASCII表
- 三、选择语句、循环语句、函数、数组
- 四、操作符、常用关键字、#define定义常量和宏
- 五、指针、结构体
注:实验环境
Windows 11 系统
Visual Studio 2019
一、 变量与常量
1. 变量及scanf函数的使用
变量的定义:类型+变量名=____; 例:int age = 24; char ch = 'd'; float weight = 49.8f;
当全局变量与局部变量同名时,局部变量优先使用。如代码中所示,输出结果为局部变量所定义的值。
在使用scanf函数时,需代码的首行加入#define _CRT_SECURE_NO_WARNINGS 1,以避免报错。若想要一劳永逸,则需在Visual Studio安装路径下搜索newsc++file.cpp文件,以记事本形式打开,将#define _CRT_SECURE_NO_WARNINGS 1复制到文件中并保存。经过以上操作,再重新打开Visual Studio软件创建新项目时#define _CRT_SECURE_NO_WARNINGS 1将自动出现在代码的第一行,使用scanf函数时即不会报错。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int sum = 46;//全局变量
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = num1 + num2;//局部变量
printf("%d\n", sum);
return 0;
} //输出结果为:输入两个操作数:>32 65
97
2. 常量
类型:字面常量、const修饰的常变量、#define定义的标识符常量、枚举常量
//字面常量演示
3.14;//字面常量
5.14;//字面常量
"abcdefkh";//字面常量
//const修饰的常变量演示,虽是常变量,本质上还是变量
#include <stdio.h>
int main()
{
const int x = 7;//此处x为const修饰的常变量
x = 689;//此处x是不能直接修改的
printf("x = %d\n", x);
return 0; //此时报错,将x = 689;删掉,结果输出为 x = 7
int x = 7;//此处x为变量
x = 689;//此处x可以修改
printf("x = %d\n", x);
return 0; //此处结果输出为 x = 689
}
//#define定义的标识符常量演示
#include <stdio.h>
#define PAI 666
int main()
{
printf("pai = %d\n", PAI);
return 0; //此处输出结果为 pai = 666
}
//枚举常量——默认值从0开始,依次向下递增1,若在开始处给MALE赋值,则在主函数中不可更改赋值
#include <stdio.h>
enum sex
{
MALE, /*此处若输入MALE = 6, 则输出结果为 6
7
8*/
FEMALE,
SECRET
};
int main()
{
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
return 0;
} /*此时输出结果为 0
1
2*/
二、常用计算机单位、数据类型、字符串、常用转义字符、ASCII表
1. 常用的计算机单位
bit (比特位) ——可存放1个二进制位
byte (字节) —— = 8 bit
kb (千字节) —— = 1024 byte
mb (兆字节,兆) —— = 1024 kb
gb (吉字节,千兆) —— = 1024 mb
tb (万亿字节,太字节) —— = 1024 gb
pb (千万亿字节,拍字节) —— = 1024 tb
2. 数据类型
类型 | 类型说明符 | 例子 | 输出形式 | 字节数 | 取值 |
---|---|---|---|---|---|
字符数据类型 | char | char ch = 'a'; | 字符:“%c\n” 字符串:“%s\n” | 1 | |
短整型 | short | short num = 10; | “%d\n” | 2 | 5位十进制数 |
整形 | int | int pai = 7; | “%d\n” | 4 | 10位十进制数 |
长整型 | long | long num1 = 7899 | “%d\n” | 4 | 10位十进制数 |
更长的整形 | long long | long long num2 = 74897 | “%d\n” | 8 | 20位十进制数 |
单精度浮点数 | float | float weight = 60.4 | “%f\n” | 4 | |
双精度浮点数 | double | double d = 0.0 | “%lf\n” | 8 |
计算数据类型的长度可以通过以下代码实现:
#include <stdio.h>
int main()
{
printf("%d\n", sizeof(char));
printf("%d\n", sizeof(short));
printf("%d\n", sizeof(int));
printf("%d\n", sizeof(long)); //C语言标准:sizeof(long) >= sizeof(int)即可
printf("%d\n", sizeof(long long));
printf("%d\n", sizeof(float));
printf("%d\n", sizeof(double));
return 0;
} /*输出结果为 1
2
4
4
8
4
8*/
3. 字符串
用双引号引起来的一串字符称为字符串字面值,简称字符串。 //例:“good morning.\n”
每个字符串结束的标志为一个 \0(即每个字符串结尾都隐藏了 \0) 的转义字符,\0 只是结束标志,不计算在字符串长度内。
通过以下代码可以突出 \0 的重要性:
//突出\0的重要性
#include <stdio.h>
int main()
{ //arr1-3为数组,数组即一组相同类型的元素
char arr1[] = "efg"; //数组内有4个元素,为efg\0
char arr2[] = { 'a','b','c' }; //数组内有3个元素
char arr3[] = { 'a','b','c','\0' }; //数组内有4个元素
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
} /*输出结果为 efg
abc烫烫烫烫蘣fg
abc*/
//arr2输出结果之所以乱码是因为没有 \0 结束标志
通过以下代码计算字符串的长度:
//求字符串长度
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "hello";
char arr2[] = { 'h','e','l','l','o'};
char arr3[] = { 'h','e','l','l','o','\0'};
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));
printf("%d\n", strlen(arr3));
return 0;
} /*输出结果为5
21
5*/
// \0不计算在长度内
// 由于arr2[]没有以\0结尾,因此输出长度值为随机值
4. 常用转义字符
转义字符 | 释义 | 例子 |
---|---|---|
\? | 书写多个问号时,防止被解析成三字母词 | ??) 为三字母词,输出为 ] \?\?) 输出为 ??) 例:printf("(are you ok??)"); 输出为 (are you ok??) |
\' | 用于表示字符常量' | printf("%d\n", '\''); 输出为 ' |
\" | 用于表示一个字符串内部的双引号 | printf("%d\n", "\""); 输出为 " |
\a | 警告字符,发出蜂鸣声 | printf("%d\n", "\a"); 输出为 电脑会发出蜂鸣声 |
\n | 换行 | |
\t | 水平制表符,相当于键盘上的Tab键 | printf("%c:\hello\text.c\n"); 输出为 c:hello ext.c |
\v | 垂直制表符 | |
\ddd | ddd 表示1-3 个八进制的数字 | printf("%c\n", "\130"); 输出为 X printf("%c\n", "\65"); 输出为 A |
\xdd | dd 表示2个十六进制数字 | printf("%c\n", "\x30"); 输出为 0 |
\b | 退格符 | |
\f | 进纸符 | |
\r | 回车 |
5. ASCII表
三、选择语句、循环语句、函数、数组
1. 选择语句
如果你好好学习,那么将会拿到好offer;如果你不好好学习,可能会学业预警。这就是一个选择。
# define _CRT_SECURE_NO_WARNINGS 1
# include <stdio.h>
int main()
{
int input = 0; //输入的值
printf("进入大学:>\n");
printf("那你要好好学习吗(1/0)?>:");
scanf("%d", &input);
if (input == 1)
{
printf("拿到一个好offer\n");
}
else
{
printf("学业预警\n");
}
return 0;
} /*输出结果为:1> 进入大学:> 2> 进入大学:>
那你要好好学习吗(1/0)?>:1 那你要好好学习吗(1/0)?>:0
拿到一个好offer 学业预警*/
2. 循环语句
有些事必须一直做,比如我们需要日复一日的学习。
C语言中可以实现循环的语句:while 语句
for 语句 (后期讲)
do while 语句 (后期讲)
//while语句演示
# include <stdio.h>
int main()
{
int grade = 0;
while (grade < 60)
{
printf("重修:%d\n", grade);
grade++; //在前一个grade值的基础上+1,即相当于 grade = grade + 1
}
if (grade == 60)
{
printf("顺利毕业\n");
}
return 0;
} /*输出结果为:重修:0
重修:1
重修:2
重修:3
重修:4
...
重修:59
顺利毕业*/
3. 函数——简化代码,可以直接调用,便捷
例: 数学中函数表示为:f(x, y) = x + y
c语言中函数表示为:f(x, y) = Add(x, y);
//加法的函数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int Add(int x,int y) //将num1赋值给x,num2赋值给y,z赋值给sum
{
int z = x + y;
return z;
} //定义Add函数功能
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0; // = 0 是将变量初始化
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = Add(num1, num2);
printf("sum = %d\n", sum);
return 0;
} /*输出的结果为:输入两个操作数:>87 98
sum = 185*/
4. 数组
4.1 数组定义:一种相同类型元素的组合,是用下标来进行访问的。
例:int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // arr为数组的名称,[]内的数字为元素的个数,[10]表示该整形数组中最多有10个元素。
char ch[5] = {'a', 'b', 'c'}; //不完全初始化,剩余的元素默认为0。
4.2 下标定义:数组的每个元素都有一个下标,下标是从0开始的。
例: int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
下标 | arr[0] | arr[1] | arr[2] | arr[3] | arr[4] | arr[5] | arr[6] | arr[7] | arr[8] | arr[9] |
---|---|---|---|---|---|---|---|---|---|---|
元素 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
char ch[5] = {'a', 'b', 'c'};
下标 | arr[0] | arr[1] | arr[2] | arr[3] | arr[4] |
---|---|---|---|---|---|
元素(字符) | 'a' | 'b' | 'c' | ||
元素 (整形) | 97 | 98 | 99 | 0 | 0 |
将数组内元素全部打印出来 :
//while语句来实现
# include <stdio.h>
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, };
int i = 0;
while (i < 10)
{
printf("%d ", arr[i]);
i++;
}
return 0;
} //输出结果为:1 2 3 4 5 6 7 0 0 0
//for语句来实现
# include <stdio.h>
int main()
{
int i = 0;
char ch[5] = { 'a', 'b', 'c' };
for (i=0; i<5; i++)
{
printf("%c ", ch[i]);
}
printf("\n");
return 0;
} //输出结果为:a b c
//因为打印部分输出的为字符,所以 0 0 不能输出
数组长度的计算在后面单目操作符部分中给出。
四、操作符、常用关键字、#define定义常量和宏
1. 操作符
1.1 算数操作符 + - * / %
需要特别注意的为:/ 除,结果为商值。若想结果输出为小数值,则除数和被除数中至少有一个为小数。 例:9/2=4;9.0/2=4.5;9/2.0=4.5
% 取模(余),结果为余数。 例:3%2=1;7%3=1
#include <stdio.h>
int main()
{
int a = 9 / 2;
float b = 9.0 / 2;
float c = 9 / 2.00;
int d = 10 % 4;
printf("%d\n", a);
printf("%f\n", b);
printf("%f\n", c);
printf("%d\n", d);
return 0;
} /*输出结果为:4
4.500000
4.500000
2*/
1.2 移位操作符——移动的是二进制位 >> <<
>> 右移 —— 相当于乘以2
<< 左移 —— 相当于除以2
例:当 int a=8;时,a=8对应的二进制位为1000
因为a为整形,即4个字节,32个比特位
所以 int a=8 对应的二进制为:00000000000000000000000000001000 8
左移一位为:00000000000000000000000000010000 16
右移两位为:00000000000000000000000000000010 2
#include <stdio.h>
int main()
{
int a = 8;
int b = a << 1;
int c = a >> 2;
printf("%d\n", b);
printf("%d\n", c);
return 0;
} /*输出结果为:16
2*/
1.3 位操作符 & ^ |
& 按位与
^ 按位异或
| 按位或
1.4 赋值操作符 = += -= *= /= &= ^= |= >>= <<=
例:int a = 2;
int a = a + 5;
以上可简化写成:int a += 5;
1.5 单目操作符 ! - + & sizeof ~ -- ++ * (类型)
单目操作符:只有一个操作数。 例:-a
双目操作符:有两个操作数。 例:a-b
单目操作符 | 用法 |
---|---|
! | 逻辑反操作 |
- | 负值 |
+ | 正值 —— 一般省略 |
& | 取地址 |
sizeof | 计算操作数的类型长度(单位为字节)—— 可计算类型、变量、数组的大小 |
~ | 对一个数的二进制按位取反 |
-- | 前置、后置-- |
++ | 前置、后置++ |
* | 间接访问操作符(解引用操作符) |
(类型) | 强制类型转换 |
1.5.1 ! 逻辑反操作
C语言中,0表示假;非0表示真。
用法:if (a) //如果a为真
if (!a) //如果a为假
// ! 逻辑反操作
#include <stdio.h>
int main()
{
int a = 10; // a=10为非0,为真,所以!a输出结果为0
int b = 0; // b=0,为假,所以!b输出结果为真,真的输出值均为1
printf("%d\n", !a);
printf("%d\n", !b);
return 0;
} /*输出结果为:0
1*/
1.5.2 sizeof 长度计算操作符
sizeof 可以计算类型、变量和数组的大小,单位为字节。
如下代码中,计算数组的大小的输出值为40是因为该数组中有10个元素,每个元素为1个整形,一个整形为4个字节,因此输出值为40;
计算数组中元素个数是利用数组的总大小/一个元素的大小 = 个数。
// sizeof 长度计算操作符
#include <stdio.h>
int main()
{
int a = 10;
int arr[10] = { 2 };
int sz = sizeof(arr) / sizeof(arr[2]);
printf("%d\n", sizeof(int)); //计算类型的大小
printf("%d\n", sizeof(a)); //计算变量的大小
printf("%d\n", sizeof(arr)); //计算数组的大小
printf("%d\n", sizeof(arr[0])); //计算数组的大小
printf("%d\n", sizeof(sz)); //求数组元素个数
}
/*输出结果为:4
4
40
4
4*/
1.5.3 ~ 对一个二进制数进行按位取反——位指的是二进制位
记住位打印类型及三码(原码、反码、补码)转换规则即可。
按位取反———将所有位全部取反,即将所有二进制位中数字 0变成1,1变成 0。
一个整数中的二进制表示有3种:原码、反码、补码。(正整数三码相同,负整数则需计算。)
针对负数计算方式:1. 写出二进制数的原码序列,一个整数的二进制序列最高位为符号位(负数的符号位为1),其余为有效位;
2. 原码序列的符号位不变,有效位取反得到反码序列;
3. 反码序列的符号位不变,有效位加1得到补码序列。
例:二进制数 -1;—— 为整形,有4个字节,即32比特位。
原码:10000000000000000000000000000001
反码:11111111111111111111111111111110
补码:11111111111111111111111111111111
整数在内存中存储的是补码;%d打印出来的为真实值,即原码。
例:int a = 0;
a 二进制为:00000000000000000000000000000000 (32位)
~a 二进制位:11111111111111111111111111111111 (补码)(32位)
11111111111111111111111111111110 (反码)
10000000000000000000000000000001 (原码)
所以输出的数值为:-1
// ~按位取反操作符
#include <stdio.h>
int main()
{
int a = 0;
printf("%d\n", ~a);
return 0;
} //输出结果为:-1
1.5.4 -- ++ 前置、后置 -- ++
//前置-- ++操作符
#include <stdio.h>
int main()
{
int a = 34;
int b = ++a; //先++,后使用
printf("%d\n", b);
printf("%d\n", a);
return 0;
} /*输出结果为:35
35*/
//后置-- ++操作符
#include <stdio.h>
int main()
{
int a = 34;
int b = a--; //先使用,后--
printf("%d\n", b);
printf("%d\n", a);
return 0;
} /*输出结果为:34
33*/
//前置、后置-- ++操作符
#include <stdio.h>
int main()
{
int a = 28;
int b = a--; //先使用,后--
int c = ++b;
printf("%d\n", b);
printf("%d\n", a);
printf("%d\n", c);
return 0;
} /*输出结果为:29
27
29*/
//不建议研究
#include <stdio.h>
int main()
{
int a = 2;
int b = (++a) + (++a) + (++a) + (++a); //++a优先级最高,先算出++a的最终值为6,在进行四个6相加
printf("%d", b);
return 0;
} //输出结果为:24
1.5.5 (类型) 强制类型转换符——类型不匹配时使用,不推荐使用
//带小数点的默认为double类型——小数可以有1215位,float小数可以有6位
#include <stdio.h>
int main()
{
int a = 3.14;
printf("%d", a);
return 0;
} //输出结果为:3
//此时会警告有丢失数据的可能,因为3.14为double类型
//正确写法
#include <stdio.h>
int main()
{
int a = (int)3.14;
printf("%d", a);
return 0;
} //输出结果为:3
1.6 关系操作符 > >= 大于等于 < <= != 不等于 == 等于
1.7 逻辑操作符 && II
&& 逻辑与——并且 有一假则为假,两同为真则为真
|| 逻辑或——或者 有一真则为真,两同为假则为假
#include <stdio.h>
int main()
{
int a = 3;
int b = 0;
int c = 5;
int d = 0;
int e = a && b;
int f = a && c;
int g = b && c;
int h = a || b;
int i = a || c;
int j = b || c;
printf("%d ", e);
printf("%d ", f);
printf("%d ", g);
printf("%d ", h);
printf("%d ", i);
printf("%d ", j);
return 0;
} // 输出结果为:0 1 0 1 1 1
1.8 条件操作符 exp1 ? exp2 : exp3
即三目操作符,有三个操作数,分别为 exp1 exp2 exp3
若 exp1 成立,则 exp2 计算,整个表达式的结果为:exp2 的结果;
若 exp1 不成立,则 exp3 计算,整个表达式的结果为:exp3 的结果;
例:求较大值、较小值
//条件操作符 exp1 ? exp2 : exp3
#include <stdio.h>
int main()
{
int a = 6;
int b = 9;
int max = 0;
int min = 0;
max = a > b ? a : b;
min = a < b ? a : b;
printf("max=%d\n", max);
printf("min=%d\n", min);
return 0;
} /*输出结果为:max = 9
min = 6*/
1.9 逗号表达式 exp1, exp2, exp3, ...expN
特点:从左到右依次计算,整个表达式的结果为最后计算的结果。
//逗号表达式 exp1, exp2, exp3, ...expN
#include <stdio.h>
int main()
{
int a = 2;
int b = 9;
int c = 7;
int d = (b = a + 7, c = b - 3, b = c + 4); //从左到右依次计算:b = 9 c = 6 b =10
printf("%d\n", d);
return 0;
} //输出结果为:10
1.10 下标引用、函数调用和结构成员 [] () . ->
int arr[10] = { 1,2,3,4,5,6,7 };
printf("%d", arr[5]); //[]下标引用 ()调用函数
//调用函数时,函数名后边的()即为函数调用操作符,可以传递0-多个参数
2. 常见关键字
auto 是自动的 | break 循环/switch语句 | case | char | const 修饰常变量 | continue 继续 | default 默认 | do | double | else | enum 枚举 |
extern 声明外部符号的 | float | for | goto | if | int | long | register | return 返回 | short | signed 有符号的 例:20,-1 |
sizeof | static 静态的 | struct 结构体 | switch 语句 | typedef 类型定义 | union 联合体(共用体) | unsigned 无符号的 | void 无/空 | volatile | while 循环 |
2.1 auto 是自动的
auto 是自动的——每个局部变量都是auto修饰的。 新的c语言语法中也有其他的用法,暂不考虑。 例:auto int = 10; //a是自动创建,自动销毁的—自动变量。 auto一般省略。
2.2 extern 声明外部符号关键字
声明函数只需给出:函数类型、函数声明、参数类型。
例:extern int add(int x, int y);
2.3 register 寄存器关键字
register 寄存器关键字——大量/频繁被使用的数据想放到寄存器中,提升效率。但意义不大。 例:register int num = 100; //建议num的值存放到寄存器中,但是是否放到寄存器中是由编译器决定的。
计算机中数据可以存储到:寄存器、高速缓存、内存、硬盘、网盘中。
早期的:CPU——内存 CPU运行过快,但内存速度跟不上,会导致CPU闲置。
现在(如上图):CPU处理数据时,在内存基础上提供一个高速缓存,在高速缓存基础上提供一个寄存器。CPU拿数据时先去寄存器中拿,再去高速缓存中拿,再去内中拿。z——如图中蓝色箭头所示。 整体效率提升。
- 当处理寄存器数据时,将高速缓存中数据拿过来;处理高速缓存数据时,将内存中数据拿过来。因此大部分数据都可以在寄存器中找到,找不到去高速缓存中找,再找不到去内存中找。
2.4 typedef 类型重命名
typedef 类型重命名——使类型变得简单使用。
//typedef 类型重命名
#include <stdio.h>
typedef unsigned int uint_x; //将unsigned int重命名为uint_x,所以uint_x也是一个类型名
int main()
{
unsigned int num1 = 4;
uint_x num2 = 0; //与上行的代码具有相同的意义
printf("%d\n", num1);
printf("%d\n", num2);
return 0;
} /*输出结果为:4
0*/
2.5 static 静态的
static 静态的——用来修饰变量和函数的。
三种用法:1. 修饰局部变量——称为静态局部变量
2. 修饰全局变量——称为静态全局变量
3. 修饰函数——称为静态函数
2.5.1 修饰局部变量——当我们希望一个变量除了它的范围后不销毁,则用此类修饰
- 出循环后变量值不销毁,自动保留上一次的计算值。
- 改变了局部变量的生命周期——本质上是改变了变量的存储类型(a由栈区→静态区)。
- static修饰的局部变量让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。
对比代码1和代码2即可理解static修饰局部变量的意义:
//static修饰局部变量 静态局部变量
//代码1
#include <stdio.h>
void test()
{
int a = 7; //a为局部变量
a++;
printf("%d ", a); //循环一次打印后出循环即消失,下一次循环a值仍然为7
}
int main()
{
int i = 0; //代码开始
for (i = 0; i < 10; i++) //循环10次结束
{
test();
}
return 0;
} //输出结果为:8 8 8 8 8 8 8 8 8 8
//代码2
#include <stdio.h>
void test()
{
static int a = 7; //a为static修饰的局部变量
a++;
printf("%d ", a); //循环一次打印后出循环即消失,下一次循环a值为上一次循环的结果
}
int main()
{
int i = 3; //代码开始
for (i = 3; i < 10; i++) //循环7次结束
{
test();
}
return 0;
} //输出结果为:8 9 10 11 12 13 14
2.5.2 修饰全局变量
- 一个全局变量被static修饰,会使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。
- 全局变量——在其他源文件内部可以被使用,是因为全局变量具有外部链接属性。但是被static修饰后,就变成了内部链接属性,其他源文件就不能链接到这个静态的局部变量了。
//static修饰全局变量 两个源文件
//代码1
//源文件1
int x = 2018;
//源文件2
#include<stdio.h>
extern int x;
int main()
{
printf("%d\n", x);
return 0;
} //输出结果为:2018
//代码2
//源文件1
static int x = 2018;
//源文件2
#include <stdio.h>
extern int x;
int main()
{
printf("%d\n", x);
return 0;
} //报错!1.无法解析的外部符号“int x”。2.无法解析的外部命令。
2.5.3 修饰函数
- 一个函数被static修饰,会使得这个函数只能在本源文件内使用,不能在其他源文件内使用。
- 本质上:static是将函数的外部链接属性转变为内部连接属性。(与修饰全局变量一致)
//static修饰函数
//代码1
//源文件1
int add(int a, int b)
{
return a + b;
}
//源文件2
#include<stdio.h>
extern int add(int a, int b);
int main()
{
printf("%d\n", add(6, 8));
return 0;
} //输出结果为:14
//代码2
//源文件1
static int add(int a, int b)
{
return a + b;
}
//源文件2
#include<stdio.h>
extern int add(int a, int b);
int main()
{
printf("%d\n", add(6, 8));
return 0;
} //输出结果为:报错!1.无法解析的外部符号。2.无法解析的外部命令。
3. #define定义常量和宏
- define是一个预处理指令,并不是关键字。——与include相同。
//define定义常量
#define MAX = 100; //在变量与常量部分已经涉及到,有详细代码
//define定义宏
//代码2
#define add(x,y) ((x)+(y))
#include<stdio.h>
int main()
{
int sum = add(7, 5);
printf("sum=%d\n", sum);
printf("num=%d\n", 5*add(7,5)); //5*(7+5)
return 0;
} /*输出结果为:sum = 12
num = 60*/
//代码2
#define add(x,y) x+y
#include<stdio.h>
int main()
{
int sum = add(7, 5);
printf("sum=%d\n", sum);
printf("num=%d\n", 5 * add(7, 5)); //5*7+5
return 0;
} /*输出结果为:sum = 12
num = 40*/
五、指针、结构体
1. 指针
- 两种用法:1. 用来存放别人的地址; 2. 通过 *P 找到所指向的对象,来操作所指向的对象。
1.1 内存——与现实中空间的使用十分类似
- 内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的。
- 为了有效的使用内存,就把内存划分成一个个的内存单元,每个内存单元的大小是1个字节。
- 为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
打印变量地址:
//打印变量地址
#include <stdio.h>
int main()
{
int num = 10; //num在内存中分配的空间为4个字节
char ch = 'h';
printf("%p\n", &num); //%p是专门用来打印地址的
printf("%p\n", &ch);
int* Pa = # //P是用来存放地址的,在c语言中叫做指针变量
char* Pb = &ch; //*说明P是指针变量,int说明P执行的对象是int类型的
return 0; //取出num的地址,
}
/*输出结果为:00BBFCBC
00BBFCB3*/
通过 *P 找到所指向的对象,来操作所指向的对象:
//通过 *P 找到所指向的对象,来操作所指向的对象
#include <stdio.h>
int main()
{
int a = 10;
float b = 3.14;
int* P = &a;
float* Pa = &b;
*P = 20; //这里的*P叫做解引用操作,*P就是通过P的地址找到a
*Pa = 5.14;
printf("%d\n", a);
printf("%f\n", b);
return 0;
} /*输出结果为:20
5.140000*/
1.2 指针变量的大小
-
指针的大小与地址线的多少有关,而地址线由于32位、64位平台有关
- 32位——32根地址线——物理线——通电——1/0的二进制序列 (电信号转换成数字信息);64位——64根地址线——物理线——通电——1/0的二进制序列 (电信号转换成数字信息)。
- 指针变量的大小取决于地址的大小——因为指针是用来存放地址的指针需要多大空间取决于地址的存储需要多大空间。
- 32位平台下地址是32个bit位(即4个字节);64位平台下地址是64个bit位(即8个字节)。
//计算指针变量的大小
#include <stdio.h>
int main()
{
printf("%d ", sizeof(char*));
printf("%d ", sizeof(short*));
printf("%d ", sizeof(int*));
printf("%d ", sizeof(double*));
printf("%d ", sizeof(long*));
printf("%d ", sizeof(long long*));
printf("%d ", sizeof(float*));
printf("%d ", sizeof(double*));
return 0;
} //32位系统输出结果为:4 4 4 4 4 4 4 4
//64位系统输出结果为:8 8 8 8 8 8 8 8
2. 结构体
- 结构体使得C语言有能力描述复杂类型。
- 结构体可以让C语言创建新的类型出来。
例:描述学生,包含 名字+年龄+性别+学号+成绩 几项信息:
//结构体的初始化
#include <stdio.h>
struct Stu //stu为结构体变量
{
char name[20]; //名字,为字符数字
int age; //年龄
char sex[5]; //性别
char id[15]; //学号
double score; //成绩 以上5项为成员变量
};
int main()
{
//.为结构成员访问操作符
struct Stu s = { "李明", 20, "男", "2209699710", 90.4 }; //结构体的创建和初始化
printf("1:name=%s age=%d sex=%s id=%s score=%f\n", s.name, s.age, s.sex, s.id, s.score); //结构体变量.成员变量
//->操作符——功能与(*P)相同
struct Stu* Ps = &s;
printf("2:name=%s age=%d sex=%s id=%s score=%f\n", Ps->name, Ps->age, Ps->sex, Ps->id, Ps->score); //结构体指针->成员变量名
printf("3:name=%s age=%d sex=%s id=%s score=%f\n", (*Ps).name, (*Ps).age, (*Ps).sex, (*Ps).id, (*Ps).score);
return 0;
} /*输出结果为:1:name = 李明 age = 20 sex = 男 id = 2209699710 score = 90.400000
2:name = 李明 age = 20 sex = 男 id = 2209699710 score = 90.400000
3:name = 李明 age = 20 sex = 男 id = 2209699710 score = 90.400000*/