认识C语言①
一、C语言的定义
C语言是一门面向过程的计算机编程语言,广泛应用于底层开发
二、 了解知识(VS2013)
1、程序文件
- 头文件(保存程序声明的文件) ——“ .h ” 后缀指C/C++程序的头文件
- 定义文件(保存程序实现的文件)—— “ .c ” 后缀指C程序的定义文件 , “ .cpp ” 后缀指C++程序的定义文件
2、主函数
主函数main()是程序的入口,一个项目只能拥有一个主函数。程序一定会从main()的第一行开始执行。
一般采用格式 :
int main()
{
return 0;
}
3、#define _CRT_SECURE_NO_WARNINGS
使用VS编译器时,在整个源文件第一行敲上这句话。因为在VS中,它认为比如像:scanf ( ) , strcpy ( ) , strcat ( ) …都是不安全的,会报错,加上这个就可以避免。
4、关于调试
(1)Debug和Release
Debug叫调试版本,它包含调试信息,且没做任何优化,便于程序员调试;Release叫发布版本,是让测试人员调试的,它是已经经过了各种优化,使程序在代码大小和运行速度上都达到最优的版本。Release版本最终是要发送给用户的,发给用户的版本必须要没有问题,测试人员就是最后一个把关的。
(2)写出易调试好代码的小技巧
- 尽量使用宏assert()
assert——断言,它是一个宏,头文件是<assert.h>,assert(表达式)作用是判断表达式里的表达式的值,当为假时就会直接结束程序运行并且报错,所以叫断言,当然若是程序正确啥也不做。 - 尽量使用关键字const
在给变量赋值时在前面加上const,它就自动默认等号左边是变量名,右边是常值,若是不符合这个就会直接报错。另外被附上const的变量,具有了常量属性,即它的值不可以再改变。(这里说一下指针变量:const * p 修饰指针指向的内容,所以指针指向的内容不可改变;* const p修饰指针,所以指针本身不可以改变)
(2)两个典型错误
- 实现n的阶乘求和
#include <stdio.h>
int main() {
int i = 0;
int j = 0;
int ret = 1;
int sum = 0;
int input = 0;
scanf("%d", &input);
for (i = 1;i <= input;i++) {
//ret置1加在这里:ret = 0;
for (j = 1;j <= i;j++) {
ret *= j;
}
sum += ret;
}
printf("%d\n", sum);
return 0;
}
计算完每个数字的阶乘之后,会跳出内层循环,跳去执行下一个数字的阶乘ret,然后把它们加起来,但是每次得到的阶乘都是在上一个数字的基础上再乘的,这样得到的结果一定是错误的。
正确做法是:内层循环每计算完一个数字的阶乘就加到总和sum里,然后计算下一个数之前把ret置1。这样得到的结果就是最终的正确答案。
- 数据溢出
#include <stdio.h>
int main() {
int i = 0;
int arr[] = { 1,2,3,4,5 };
for (i = 0; i < 8; i++) {
arr[i] = 0;
printf("@#$%\n");
}
return 0;
}
猜猜计算结果?
结果是代码会进入死循环,本来数组的大小是五个整型的值,但是循环要走到 arr[7] 时,经过调试发现它的地址和 i 的地址一样!
那就意味着,循环走到 arr[7] 时,i 的值又被赋回了0,那么这个循环将永远跳不出!
在栈区里,是先使用高地址空间,所以 i 的赋值先存到了栈区,但是数组是随着下标变大,地址由低到高,这就是造成这个尴尬局面的根本原因!
三、数据类型(64位操作系统)
数据类型 | 类型名 | 占用空间 | 取值大小 |
---|---|---|---|
char | 字符型 | 1 byte(8位) | \ |
int | 整型 | 4 byte(32位) | -231~231-1 |
short | 短整型 | 2 byte (16位) | -215~215-1 |
long | 长整型 | 8 byte ( 64位 ) | -215~215-1 |
long long | 更长整型 | 8 byte (64位) | -263~263-1 |
float | 单精度浮点数 | 4 byte (32位) | -231~231-1 |
double | 双精度浮点数 | 8 byte(64位) | -263~263-1 |
可以使用sizeof()去计算类型创建变量所开辟的空间大小。
四、变量和常量
C语言中不变的值指常量,改变的值指变量。
1、变量
分类
……局部变量:放到{ }里面
……全局变量:放在{ }外,尽量避免使用(防止冲突和安全性)
当局部变量和全局变量的名字一样时,系统优先使用局部变量
作用域和生命周期
作 用 域 限定一个名字的可用性的代码范围。(对于局部变量来说,在定义变量的{ }内,哪里使用了哪里就是其作用域;对于全局变量来说,作用域就是整个工程)
生 命 周 期一个变量从创建到销毁的这个时间段。(对于局部变量来说,进入作用域周期开始,出作用域结束;对于全局变量来说,程序的生命周期就是其生命周期)
2、常量
字面常量
直接写出的直观常量
const修饰的常变量
在定义一个变量时在其数据类型前面加上const即可。注意:常变量是一个具有常属性的变量,即它拥有一个不可以改变的值,这是常量的属性,如果定义之后再重新赋值代码会报错。但实际上它属于变量。
define定义的标识符常量
格式:#define 常量名 参数
枚举常量
生活中有些取值是可以一 一列举的且不变的,例如性别,日期…等等。我们把这样的常量叫做枚举常量。枚举关键字(enum),下面以性别举例:
enum Sex
{
MAN, //枚举常量
WOMAN //枚举常量,Sex列出的所有取值
};
int main()
{
enum Sex s=MAN;
return 0;
}