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 语言中的关键字 - 数据类型、数据修饰符及逻辑结构的更多相关文章

  1. 浅谈Java中static关键字、权限修饰符

    1.实例变量:也称非静态成员变量,实例变量前没有static关键字,用来描述同一类事物的公共属性.访问方式:对象名.变量名.实例变量存储在堆区,对象有n个,数据就有n个.实例变量随着对象的创建而创建, ...

  2. Swift语言中如何使用JSON数据教程

    这是一篇翻译文章,原文出处:http://www.raywenderlich.com/82706/working-with-json-in-swift-tutorial Swift语言中如何使用JSO ...

  3. C语言中的关键字

    1.C语言中的关键字都有实际的意义. 2.C语言中的23个关键字如下: char:声明字符型变量. short:声明短整型变量. int:声明整型变量. long:声明长整型变量. float:声明浮 ...

  4. 【转载】理解C语言中的关键字extern

    原文:理解C语言中的关键字extern 最近写了一段C程序,编译时出现变量重复定义的错误,自己查看没发现错误.使用Google发现,自己对extern理解不透彻,我搜到了这篇文章,写得不错.我拙劣的翻 ...

  5. C++中 容易忽视的const 修饰符

    C++可以用const定义常量,也可以用#define定义常量,但是前者比后者有更多的有点: (1)const常量有数据类型,而宏常量没有数据类型.编译器可以对const进行类型安全检查,而后者只进行 ...

  6. 文成小盆友python-num8 面向对象中的成员,成员修饰符,特殊成员,异常处理,设计模式之单例模式

    本节主要内容: 1.面向对象中的成员 2.成员修饰符 3.特殊成员 4.异常处理 5.设计模式之单例模式 一.面向对象中的成员(类的成员) 类的成员总共可以分为3大类,每类中有不同的分支. 1.总述, ...

  7. this关键字、访问修饰符、super关键字

    this关键字.访问修饰符.super关键字 Java关键字this只能用于方法方法体内,而且只能用在非静态方法内.当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个 ...

  8. abstract关键字、final关键字、static关键字、访问修饰符详解

     abstract关键字.final关键字.static关键字.访问修饰符详解 abstract关键字: final关键字: static关键字: 访问修饰符:

  9. C语言中的关键字总结

    1.auto 修饰局部变量,编译器默认所有局部变量都是用auto来修饰的,所以在程序中很少见到. 2.static 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...

随机推荐

  1. Ubuntu16.04下安装httpd+svn+viewVC

    一.安装httpd 1.下载httpd 网址:http://httpd.apache.org/download.cgi#apache24 下载这一条---Source: httpd-2.4.39.ta ...

  2. poj1419 Graph Coloring 最大独立集(最大团)

    最大独立集: 顶点集V中取 K个顶点,其两两间无连接. 最大团: 顶点集V中取 K个顶点,其两两间有边连接. 最大独立集=补图的最大团最大团=补图的最大独立集 #include<iostream ...

  3. springboot 关于log4j日志配置

    自动加载配置文件:(1)如果采用log4j输出日志,要对log4j加载配置文件的过程有所了解.log4j启动时,默认会寻找source folder下的log4j.xml配置文件,若没有,会寻找log ...

  4. 解决: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 ...

  5. 2019杭电多校&CCPC网络赛&大一总结

    多校结束了, 网络赛结束了.发现自己还是太菜了,多校基本就是爆零和签到徘徊,第一次打这种高强度的比赛, 全英文,知识点又很广,充分暴露了自己菜的事实,发现数学还是很重要的.还是要多刷题,少玩游戏. 网 ...

  6. Codeforces Round #568 (Div. 2) D. Extra Element

    链接: https://codeforces.com/contest/1185/problem/D 题意: A sequence a1,a2,-,ak is called an arithmetic ...

  7. 019:re_path函数详解

    re_path使用: 1.re_path和path的作用是一样的,只不过re_path在写url的时候可以使用正则表达式——功能更加强大: 2.使用正则表达式时,推荐使用原生字符串(即:已 r 开头的 ...

  8. Python连接MySQL之Python库pymysql

    连接数据库 pymysql连接数据库的方式和使用sqlite的方式基本相同: 使用connect创建连接对象 connect.cursor创建游标对象,SQL语句的执行基本都在游标上进行 cursor ...

  9. 解决"'pip' 不是内部或外部命令,也不是可运行的程序或批处理文件"的问题

    大家好,我是Connor,今天我为大家带来解决CMD命令无法直接运行 '点子' 进行安装库的问题. 今天本来想安装库来着,但是苦于pycharm的设置里不知道出了什么原因,无奈只能使用PIP功能来安装 ...

  10. Redis实战(十四)Redis实现Session共享

    序言 登录的处理流程: 1.登录页面提交用户名密码. 2.登录成功后生成token.Token相当于原来的jsessionid,字符串,可以使用uuid. 3.把用户信息保存到redis.Key就是t ...