C学习笔记(初识、概述)
常见的数据类型
类型 | 名称 | 注 | 大小 |
---|---|---|---|
char | 字符 | 通常1字节(8位) | 1 |
short | 短整型 | 2 | |
int | 整形 | -2147483648~2147483647 | 4 |
long | 长整形 | 4或8 | |
long long | 更长的整形 | 8 | |
float | 单精度浮点 | 1位符号 8为指数,23位小数 | 4 |
double | 双精度浮点 | 1位符号 11位指数 52位小数 | 8 |
C语言标准规定sizeof(long)>=sizeof(int) sizeof()表示占内存的大小
常见的打印格式
格式 | 意思 |
---|---|
%d | 打印整型 |
%c | 打印字符 |
%f | 打印浮点数字 |
%p | 以地址形式打印 |
%x | 打印16进制数字 |
%o | 打印8进制数字 |
%lf | 打印双精度小数 |
小插曲
short age = 20; //向内存申请2个字节空间
float weight=95.6; //编译器会警告,95.6默认是double型
float weight=95.6; //编译器不警告了, 但是这两句不能同时出现
全局变量与局部变量
全局变量: 定义在代码块之外
局部变量: 定义在代码块之中
// 局部变量与全局变量的名字建议不要相同,容易误会产生bug
// 当局部变量和全局变量的名字相同的时候局部变量优先。
{
{int a ;}
printf();
}
// 在这里int a相对于printf来说就是局部的。
注意 C语言语法规定,变量定义在当前代码块的最前面(规范)
变量的作用域和生命周期
作用域: 变量在哪里可以使用哪里就是作用域
局部变量作用域:变量所在的局部范围
全局变量作用域:整个工程
生命周期:
局部变量的生命周期:进入作用域生命周期就开始,出作用域生命周期就结束
全局变量的生命周期:整个程序的生命周期
全局变量的生命周期=main函数生命周期=工程的生命周期
源文件 .c 头文件 .h
-
scanf是C语言提供的(但是不安全)
-
scanf_s不是C语言提供的 VS编译器提供的(这样就没有可移植性了)
像scanf,strcopy,strlen,strcat… C语言提供的库函数好多不安全
常量
常量和变量的定义形式有所差异
常量: 1. 字面常量 2. const修饰的常变量 3. #define定义的标识符常量 4. 枚举常量
3; // 字面常量,直接写出来的值
const int num = 4; // const修饰 将变量变为常量 -> 常变量
#define MAX 10 // 没有“=” 没有“;”
//枚举关键字
enum Sex{
MALE,FEMALE,SECRET //最后一个没有逗号
}; // 最后是分号
int main(){
enum Sex s = FEMALE;
return 0;
}
字符串
由双引号引起的一串字符
存储:
存储在数组中
char a[]="abc"; // 实际上数组内是{'a','b','c',0} 最后的0实际是"\0"
输出时 printf("%s\n",a);
注:字符串的结束标志是一个“\0”的转义字符,在计算字符串长度的时候\0是结束标志不算作字符串中的内容
转义字符
把原来的意思转变了
"\t" 水平制表符 "\n" 回车 "\v"垂直制表 "\ddd" ddd表示1-3个八进制数 "\xdd" dd表示2个十六进制数字
注释
//
/* */
函数
int Add(int x,int y){ //第一个int是函数的返回值类型
int z = x + y;
return z;
}
int main(){
int a=2,b=3;
c=Add(2,3); // 调用自定义函数
return 0;
}
数组
int arr[10];
int arr2[3]={1,2,3};
// 数组下标从0开始 通过下标访问元素
操作符
算数运算符 + - * / %
移位操作符 << >> 左移 右移 移的是二进制位 //移完之后右边补0左边舍弃
位操作符 & ^ | 按位与 按位异或 按位或
异或:对应的二进制位相同为0 相异为1
a = a + 10 <=> a += 10 (变量)+(运算符)+(=)+(值)
单目操作符 1个操作数
双目操作符 2个操作数
三目操作符 3个操作数
"&" 取地址符
sizeof 操作数类型长度
"~" 对二进制按位取反
"--" 前置与后置的
"++" 前置与后置的
"(类型)" 强制类型转化
"\*" 间接访问提示符(解引种操作符)
对于sizeof
int arr[10]={0}; //10个整型元素的数组
printf("%d\n",sizeof(arr));//10*sizeof(int)=40
获取数组大小:sizeof(arr)/sizeof(arr[0]); //数组大小=数组的总大小/每个元素的大小
关系操作符 > < >= <= != ==
逻辑操作符 && || // 真:非0 假:0
条件操作符:(三目运算符)
表达式1 ? 表达式2 : 表达式3;
下标引用操作符 []
函数引用操作符 ()
“&” “*” “.” “->” 这4个之后写
码
最高位是1是负数 最高位是0是正数
对于正数:原码、反码、补码相同
对于负数:原码:直接按照正负,写出的二进制序列
-》反码:原码的符号位不变其他位取反
-》补码:反码+1
只要是整数内存中存储的就是二进制的补码
例:-2(假设是8位,实际上有32或64位)
10000010 原码
11111101 反码
11111110 补码
关键字
register:
register int a = 10; //把a定义成寄存器变量(只是一个建议操作)
signed 有符号
signed int ; // signed一般省略
unsigned int num = 0; // 无符号数
struct 结构体关键字
union 联合体/共用体
typedef 类型定义
typedef unsigned int u_int;//类型重定义 将unsigned int重命名为u_int
unsigned int num1 = 20;//原来的定义方式可以使用
u_int num2 = 10;//其实就是相当于别名
关键字static
static int a = 1;// a是一个静态的局部变量
static修饰局部变量,局部变量的声明周期变长
static修饰全局变量,改变了变量的作用域–让静态的全局变量智能在自己的源文件内部使用
注:
外部写函数如 a.c中写的函数int Add(int x,int y)在b.c中调用时
extern int Add(int,int);//声明方式,声明后可以理解为在a.c中自己定义函数
static修饰外部函数a.c中static int Add(int x, int y)在b.c中不能通过编译。也就是相当于改变了Add()的作用域
static修饰函数改变了函数的链接属性
#define 定义标识符、宏定义
#define MAX 100 //将代码中的MAX替换为100
#define MAX(X,Y) (X>Y ? A : B) //将代码中的MAX(X,Y)替换成(X>YA:B)
指针
关于地址
printf("%p \n",&a);//%p地址格式 &a取a的地址
int* p = &a;
//int*指针类型
//p 指针变量
//&a 取地址
使用
*p //解引用操作符
int a =10; //在内存中存储10 还有char*等类型
int* p = &a;//定义指针,位置为a的内存
*p = 20; //更改指针指向内存的 值
printf("a= %d",a);//结果为a=20
指针大小
指针在32位平台上是4个字节4×8=24,在64位平台上是8字节8×8=64
int* p的理解 p是int类型的一个指针(仅此而已),一般*p指向的也是一个int型的
结构体
描述复杂对象——我们自己创造出来的一个类型
struct Book{
char name[20];
short price;
}; //这里有个分号
//在main中使用
struct Book b1 = {"C语言程序设计",55};//创建一个该类型的结构体的变量
结构体变量的使用
printf("书名:%s",b1.name);
printf("价格:%d",b1.price);
重新赋值
#include <string.h>
strcpy(b1.name,"C++"); //因为name是一个数组不是一个变量
b1.price = 15;
指针定义
struct Book* pb = &b1;
使用指针
printf("%s\n",pd->name);//一般使用这种形式
printf("%d\n",(*pd).price);//这种比较啰嗦
// . 结构体变量.成员
// -> 结构体变量->成员