C 语言中的关键字 - 数据类型、数据修饰符及逻辑结构
C 语言中有 32 个关键字。这是留个编译器用的特殊字符串,用户不可以使用。
特殊关键字
sizeof 和 return 是 C 语言中的两个特殊关键字。
sizeof
sizeof 用于计算变量所占内存空间的字节数,返回值为 unsigned long 无符号长整型。sizeof 不依赖底层操作系统,可以在编译时直接得到。
有两种用法:
int a;
printf("%lu\n", sizeof(a));
printf("%lu\n", sizeof a);
return
return 用于执行返回操作,退出当前函数,执行函数调用栈的上一层调用者。
数据类型
C 语言中,各种数据类型所占空间大小,跟具体的编译平台相关。例如在 32bit 机器上 int 类型占 4Byte。
CPU 在一个周期内所能处理数据的最优大小,就是 CPU 的位数,也是对应平台上 int 类型的大小。
整型和浮点型
所有的数值类型,默认都是带符号的。如果想使用不带符号的数值,必须用 unsigned 关键字明确指定,例如 unsigned int
。
- 整型类型
char:占 1 个字节,是最小的数据类型。有符号字符型表示范围为 -128~127,无符号字符型表示范围为 0~ 255
short:一般占 2 字节
int:2 字节(16 bit CPU)或 4 字节(32 bit CPU)。有符号 int 型表示范围为 -32768~32767,无符号 int 型表示范围为 0~ 655355
long:4 字节或 8 字节,可以拼接long long l
表示更大的数据。 - 浮点类型
float:4 字节
double:8 字节
浮点数有多种不同的表示方法,虽然表示范围很大,但是可能有精度丢失。浮点数默认是 double 类型,但可以在浮点数末尾加个 f 来表示采用 float 类型,例如:
float f = 3.14 * 2; // 3.14 会分配一个 double 类型的空间
float f2 = 1.234f + 2.333f;
无符号和有符号
所有的数值类型,默认都是带符号的。如果想使用不带符号的数值,必须用 unsigned 关键字明确指定,例如 unsigned int
。
通常来说,可以进行各种运算的数值用默认的有符号类型,而单纯的数据(例如信号、二进制数据)则使用无符号的类型。
有符号数的位运算
- 对于有符号整数,每一次右移操作采用的是sar算术右移指令,高位补充的是1
- 对于无符号整数,每一次右移操作采用的是shr逻辑右移指令,高位补充的是0
- 对于左移,无论是算术左移(sal)还是逻辑左移(shl),低位补充的都是0
#include <stdio.h>
int main()
{
char c1 = 0x80;
unsigned char c2 = 0x80;
printf("0x%x\t0x%x\n", c1, c2);
int i;
for (i = 0; i < 8; i++) {
c1 = c1 >> 1;
c2 = c2 >> 1;
printf("0x%x\t0x%x\n", c1, c2);
}
}
输出:
0xffffff80 0x80
0xffffffc0 0x40
0xffffffe0 0x20
0xfffffff0 0x10
0xfffffff8 0x8
0xfffffffc 0x4
0xfffffffe 0x2
0xffffffff 0x1
0xffffffff 0x0
void 类型
void 相当于一个占位符,可以声明变量或返回值,但是void 类型的变量不可直接使用,需要强制转换为其他类型才可以。
void a;
void fun();
void 通常用于:
- 对函数返回的限定
- 对函数参数的限定
溢出
每种数据类型在存储数据时,都有范围限制。如果把超过限制的数据存入某个变量,会导致各种异常状况。编译时会有警告。
char c = 666;
printf("%d", c);
输出:
/code/main.c: In function ‘main’:
/code/main.c:5:1: warning: overflow in implicit constant conversion [-Woverflow]
char c = 666;
^
-102
自定义数据类型
struct、union、enum 是 3 种自定义的数据类型,typedef 是为数据类型起一个别名。
自定义数据类型,就是把已有的数据类型进行组合,得到一个匹配实际的资源类型的存储类型。
使用自定义数据类型时,必须在变量前指明这个变量是哪一个数据类型,例如 struct MyStruct s;
struct 结构体
struct 结构体就是变量的集合,把已有的类型组合到一起,形成新的类型的语句。struct 中的变量按照顺序存储。
struct 也是一条语句,定义时必须以分号结尾。使用时必须用 struct 自定义的名称 变量名
的形式来声明变量,示例:
#include <stdio.h>
struct People {
unsigned int age;
char* name;
}; // 这里必须加分号
int main()
{
struct People s = {20, "jack"};
printf("%d, %s", s.age, s.name);
}
union 共用体
union 共用体中,所有变量共享同一块内存。因为内存的起始地址重合,任何时刻都只能存储一个变量。
#include <stdio.h>
union myUnion {
unsigned int i;
char c;
}; // 这里必须加分号
int main()
{
union myUnion s;
s.i = 666;
printf("%d", s.i);// s 中只有 i 一个元素,如果打印 c 会报错
s.c = 'a';
printf("%c", s.c);// s 中只有 c 一个元素,如果打印 i 会报错
}
输出为:``666a
enum 枚举
C 语言中能用 enum 实现的代码,都可以不用 enum 实现。
enum 是常量的集合。例如一周的七天,可以用 #define 或 const int 来定义,也可以打包放到 enum 中。enum 特点是:
- enum 中首元素默认是 0,可以指定为任意 int 类型的整数,后序所有元素依次加一。
- enum 枚举类型可以不指定名称,因为 enum 中的每一个元素都可以当做全局常量直接使用
下面示例中的三种写法等价,用法是一样的:
#include <stdio.h>
/*
#define SUN 7
#define MON 1
#define TUE 2
const int SUN = 7;
const int MON = 1;
const int TUE = 2;
*/
enum {SUN = 0, MON, TUE}; // 默认第一个元素是0,后序元素依次加一
int main()
{
printf("%d\n", TUE);
}
typedef
typedef 为已有的数据类型起别名,可以让程序可读性更高。通常在 Linux 内核源码中,用 typedef 起的别名,后缀都是 _t
。
#include <stdio.h>
typedef unsigned int uint_t;
int main()
{
uint_t a = 666;
printf("%d", a);
return 0;
}
逻辑结构
分支语句
if else 语句
if (3 < 4)
{//...}
switch case default 语句
语法:
switch(整型变量)
{
case 整型数字:
// 执行语句
break; // 必须加,否则会向下执行
default:
// 上面没有匹配到时,默认执行这里的语句
}
#include <stdio.h>
int main()
{
int i;
for (i = 0; i < 5; i++)
{
switch (i/3)
{
case 0:
printf("%d\n", i);
case 1:
printf("%d\n", i);
case 2:
printf("%d\n", i);
break;
default:
printf("this is default\n");
}
}
}
因为没加 break 会导致 switch case 贯穿,输出如下:
0
0
0
1
1
1
2
2
2
3
3
4
4
循环语句
for 循环
跟次数相关。
C 语言中,for 循环的初始化语句中,必须用已经声明过的变量,比较差:
int i;
for (i = 0; i < 10; i++)
{//...}
do while 循环
至少执行一次。
int a = 666;
do {
printf("%d", a);
} while (a++ < 0);
while 循环
跟条件相关。
continue、break、goto 语句
continue:结束本次循环,开始下次循环
break:结束语句所在的循环
goto:跳转到指定语句位置
类型修饰符
变量的数据类型定义之后,变量所占用的存储空间大小就固定了。变量的具体存储位置,就需要用类型修饰符来控制。默认的类型是 auto,int a
等价于 auto int a
。
- auto:变量默认的修饰符,存储在普通内存中。通过地址来寻址,可以用 & 查看具体地址。
- register:变量存储在 CPU 内部的寄存器中,速度快,容量小。& 取地址符号对这种变量无效。变量访问频率很高时,才考虑放在寄存器中。编译器会尽量把变量放在寄存器中,但如果寄存器不足,则变量还是会放在内存中。通常每个寄存器都有特殊名字,例如 ARM 的 R0,R1 等。
- static:有 3 中使用场景
- 修饰函数内变量:
static int a;
- 修饰函数外变量:
- 修饰函数:
static int fun(){}
- 修饰函数内变量:
- const:常量定义。实际上是只读变量,还是有办法修改(借助指针)。
- extern:外部声明,表示函数或变量在外部文件中
- volatile:告诉编译器,不优化编译。部分变量不仅软件可以修改,外部硬件也可以修改,编译器此时的优化可能导致错误。
C 语言中的关键字 - 数据类型、数据修饰符及逻辑结构的更多相关文章
- 浅谈Java中static关键字、权限修饰符
1.实例变量:也称非静态成员变量,实例变量前没有static关键字,用来描述同一类事物的公共属性.访问方式:对象名.变量名.实例变量存储在堆区,对象有n个,数据就有n个.实例变量随着对象的创建而创建, ...
- Swift语言中如何使用JSON数据教程
这是一篇翻译文章,原文出处:http://www.raywenderlich.com/82706/working-with-json-in-swift-tutorial Swift语言中如何使用JSO ...
- C语言中的关键字
1.C语言中的关键字都有实际的意义. 2.C语言中的23个关键字如下: char:声明字符型变量. short:声明短整型变量. int:声明整型变量. long:声明长整型变量. float:声明浮 ...
- 【转载】理解C语言中的关键字extern
原文:理解C语言中的关键字extern 最近写了一段C程序,编译时出现变量重复定义的错误,自己查看没发现错误.使用Google发现,自己对extern理解不透彻,我搜到了这篇文章,写得不错.我拙劣的翻 ...
- C++中 容易忽视的const 修饰符
C++可以用const定义常量,也可以用#define定义常量,但是前者比后者有更多的有点: (1)const常量有数据类型,而宏常量没有数据类型.编译器可以对const进行类型安全检查,而后者只进行 ...
- 文成小盆友python-num8 面向对象中的成员,成员修饰符,特殊成员,异常处理,设计模式之单例模式
本节主要内容: 1.面向对象中的成员 2.成员修饰符 3.特殊成员 4.异常处理 5.设计模式之单例模式 一.面向对象中的成员(类的成员) 类的成员总共可以分为3大类,每类中有不同的分支. 1.总述, ...
- this关键字、访问修饰符、super关键字
this关键字.访问修饰符.super关键字 Java关键字this只能用于方法方法体内,而且只能用在非静态方法内.当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个 ...
- abstract关键字、final关键字、static关键字、访问修饰符详解
abstract关键字.final关键字.static关键字.访问修饰符详解 abstract关键字: final关键字: static关键字: 访问修饰符:
- C语言中的关键字总结
1.auto 修饰局部变量,编译器默认所有局部变量都是用auto来修饰的,所以在程序中很少见到. 2.static 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...
随机推荐
- Ubuntu16.04下安装httpd+svn+viewVC
一.安装httpd 1.下载httpd 网址:http://httpd.apache.org/download.cgi#apache24 下载这一条---Source: httpd-2.4.39.ta ...
- poj1419 Graph Coloring 最大独立集(最大团)
最大独立集: 顶点集V中取 K个顶点,其两两间无连接. 最大团: 顶点集V中取 K个顶点,其两两间有边连接. 最大独立集=补图的最大团最大团=补图的最大独立集 #include<iostream ...
- springboot 关于log4j日志配置
自动加载配置文件:(1)如果采用log4j输出日志,要对log4j加载配置文件的过程有所了解.log4j启动时,默认会寻找source folder下的log4j.xml配置文件,若没有,会寻找log ...
- 解决:java compiler level does not match the version of the installed java project facet错误
java compiler level does not match the version of the installed java project facet错误的解决 因工作的关系,Eclip ...
- 2019杭电多校&CCPC网络赛&大一总结
多校结束了, 网络赛结束了.发现自己还是太菜了,多校基本就是爆零和签到徘徊,第一次打这种高强度的比赛, 全英文,知识点又很广,充分暴露了自己菜的事实,发现数学还是很重要的.还是要多刷题,少玩游戏. 网 ...
- Codeforces Round #568 (Div. 2) D. Extra Element
链接: https://codeforces.com/contest/1185/problem/D 题意: A sequence a1,a2,-,ak is called an arithmetic ...
- 019:re_path函数详解
re_path使用: 1.re_path和path的作用是一样的,只不过re_path在写url的时候可以使用正则表达式——功能更加强大: 2.使用正则表达式时,推荐使用原生字符串(即:已 r 开头的 ...
- Python连接MySQL之Python库pymysql
连接数据库 pymysql连接数据库的方式和使用sqlite的方式基本相同: 使用connect创建连接对象 connect.cursor创建游标对象,SQL语句的执行基本都在游标上进行 cursor ...
- 解决"'pip' 不是内部或外部命令,也不是可运行的程序或批处理文件"的问题
大家好,我是Connor,今天我为大家带来解决CMD命令无法直接运行 '点子' 进行安装库的问题. 今天本来想安装库来着,但是苦于pycharm的设置里不知道出了什么原因,无奈只能使用PIP功能来安装 ...
- Redis实战(十四)Redis实现Session共享
序言 登录的处理流程: 1.登录页面提交用户名密码. 2.登录成功后生成token.Token相当于原来的jsessionid,字符串,可以使用uuid. 3.把用户信息保存到redis.Key就是t ...