文章目录
- 前言
- 1. 关键字
- 2. C语言数据类型
- 3. 标志符
- 4. 常量类型
- 5. 内存模型
- 变量内存分析
- 数组
- 6. printf & scanf
- puchar&getchar
- 7 main函数
- 8 字面值常量
前言
本文简明扼要的介绍了部分C语言的一些基本内容。
1. 关键字
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|
char | short | int | long | float | double | if | else |
return | do | while | for | switch | case | break | continue |
default | goto | sizeof | auto | register | static | extern | unsigned |
signed | typedef | struct | enum | union | void | const | volatile |
基本数据类型:char, int, float, double
类型修饰: short, long, signed, unsigned
复杂类型: struct, union, enum
流程控制:分支(if, else, switch, case, default),循环(for, while, do),跳转(continue, break, goto, return)
存储类型:auto(和c++大相迳庭), register, static, extern, const, volatile
特殊用途:sizeof(同时也是运算符), typedef, void
2. C语言数据类型
3. 标志符
- 只能由字符(a~z, A~Z)、数字、下划线组成
- 不能以数字开头
- 不能是关键字
- 区分大小写
个人理解标识符是:顾名思义,标识符就是起到标志作用的符号,是给人用的,编译器会将标志符和地址关联起来;程序的运行并不需要标志符,只需要地址和值,所以标识符是给人和编译器用的。
4. 常量类型
- 整型常量
- 实型常量
- 字符常量
- 字符串常量
5. 内存模型
在笔者的环境下,不同数据类型的位数
cahr | int | float | double | short | long | long long | void* | |
---|---|---|---|---|---|---|---|---|
Byte | 1 | 4 | 4 | 8 | 2 | 8 | 8 | 8 |
#include <stdio.h>
void fun();
void fun1();
void fun2();
void fun()
{
int a = 0x04030201;
int b = 0x04030201;
int c = 0x04030201;
int d = 0x04030201;
// int *pa = &a;
printf("fun: \n");
printf("a = %p\n", &a);
printf("b = %p\n", &b);
printf("c = %p\n", &c);
printf("d = %p\n", &d);
fun1();
}
void fun1()
{
int a = 0x04030201;
int b = 0x04030201;
int c = 0x04030201;
int d = 0x04030201;
int e = 0x04030201;
// int *pa = &a;
printf("fun1: \n");
printf("a = %p\n", &a);
printf("b = %p\n", &b);
printf("c = %p\n", &c);
printf("d = %p\n", &d);
printf("e = %p\n", &e);
fun2();
}
void fun2()
{
int a = 0x04030201;
int b = 0x04030201;
int c = 0x04030201;
int d = 0x04030201;
// int *pa = &a;
printf("fun2: \n");
printf("a = %p\n", &a);
printf("b = %p\n", &b);
printf("c = %p\n", &c);
printf("d = %p\n", &d);
}
int main(int *arg, int **argvs)
{
int a = 0x04030201;
int b = 0x04030201;
int c = 0x04030201;
int d = 0x04030201;
// int *pa = &a;
printf("main: \n");
printf("a = %p\n", &a);
printf("b = %p\n", &b);
printf("c = %p\n", &c);
printf("d = %p\n", &d);
fun();
char* pa = (char*)&a;
printf("pa= %p\n", &pa);
}
OUT:
main:
a = 0x7fff04ebfa30
b = 0x7fff04ebfa34
c = 0x7fff04ebfa38
d = 0x7fff04ebfa3c
fun:
a = 0x7fff04ebf9f8
b = 0x7fff04ebf9fc
c = 0x7fff04ebfa00
d = 0x7fff04ebfa04
fun1:
a = 0x7fff04ebf9c4
b = 0x7fff04ebf9c8
c = 0x7fff04ebf9cc
d = 0x7fff04ebf9d0
e = 0x7fff04ebf9d4
fun2:
a = 0x7fff04ebf998
b = 0x7fff04ebf99c
c = 0x7fff04ebf9a0
d = 0x7fff04ebf9a4
pa= 0x7fff04ebfa40
小结:
局部变量在栈空间分配内存时,以函数为单位,先一次性分配出函数内局部变量所需的空间(函数调用不影响函数内局部变量的空间分配), 然后再执行到新的函数调用时由高地址向底地址分配内存
即: 内存的分配以函数为单位由高地址向底地址增长
变量内存分析
- 内存模型是线性的(有序的)
- 对于32位机而言,最大的内存地址是 2 32 2^{32} 232(4294967296)(4GB)
- 对于64位机而言,最大的内存地址是 2 64 2^{64} 264(171亿GB)
- CPU读写内存
- CPU运行时要明确三件事: 1. 存储单元的地址(地址信息) 2. 器件的选择,读或写(控制信息) 3. 读写的数据(数据信息)
- 通过地址总线找到存储单元的地址; 通过控制总线发送内存读写指令; 通过数据总线传输需要读写的数据;
- 变量的存储原则
- 内存内配由高地址向低地址增长
- 变量的首地址是变量存储空间低地址
- 字节序分为小端(intel, 低地址存储低位)和大端(Motorola, 低地址存储高位); 字节地址内位的存储方式是一致的
数组
char arr[3] = {'a', 'b', 'c'};
不建议使用二维数组, 在C++中使用String来处理字符串
6. printf & scanf
- 格式输出函数 printf( “格式控制字符串”, 输出项列表 );
eg: printf(“a = %d, b = %d”, a, b); - 格式控制字符串: %[标志][输出宽度][.精度][长度]类型
类型 | 含义 |
---|---|
d | 有符号十进制 |
u | 无符号十进制 |
f | 单、双精度浮点数(默认保留6位小数) |
c | 字符 |
s | 字符串 |
p | 地址 |
- scanf函数用于接受键盘输入(STDIN)的内容,是一个阻塞式函数,程序会停在scanf函数出现的地方,直到接受到数据才会继续执行。
- scanf(“格式控制字符串”, 地址列表);
eg: scanf(“%d”, &num); - 原理
- 系统会将用户输入的内容先放入输入缓冲区
- scanf方式会从输入缓冲区逐个取出内容赋值给变量
- 如果输入缓冲区的内容不为空,scanf会一直从缓冲区中获取,而不要求再次输入
- 利用setbuf清空缓冲区(所有平台都有效)
- setbuf(stdin, NULL);
puchar&getchar
char ch = 'a';
putchar(ch); // 输出a
ch = getchar(); // 获取一个字符
7 main函数
- main也是个函数名, 只不过该名比较特殊,程序已启动就会自动调用它。即,程序执行的入口。
- 如果main函数执行正常则返回0, 否则返回一个非0的数
- int main(int argc, const char* argv[]);
- argc - 在命令中输入的字符串的个数, 程序名占1个
- argv - 命令行字符串argv[0]为程序名
8 字面值常量
# 二进制
0b1010
# 十六进制
0xFF
# 八进制
0777
# 十进制
10
# 科学计数法
1e3
1.1e3
45U # 无符号
34.F # (float)34.0
2L # (long)2
2LL # (long long)2
2ULL # (unsigned long long)2