C语言集锦 | 01 - C基础语法(数据类型、输入输出、运算符、流程控制、函数、数组、static关键字)

文档版本 更新时间 更新内容
v1.0 2020-09-13 初稿完成
v1.1 2020-09-16 添加static关键字部分

一、数据类型

1. 数据类型关键字

数据类型 占用字节 范围
char 1 -128 - 127
unsigned char 1 0 - 255
short 2
unsigned short 2
int 4
unsigned int 4
long 4
unsigned long 4
long long(C99加入) 8
unsigned long long(C99加入) 8
float 4
double 8
/**
 * CPU:64bit
 * OS:Windows10
 * IDE:Clion
 * Compiler:MinGW-64
*/
#include <stdio.h>

int main() {
    
    
    printf("char:%d\r\n", sizeof(char));
    printf("short:%d\r\n", sizeof(short));
    printf("int:%d\r\n", sizeof(int));
    printf("long:%d\r\n", sizeof(long));
    printf("long long:%d\r\n", sizeof(long long));
    printf("float:%d\r\n", sizeof(float));
    printf("double:%d\r\n", sizeof(double));

    return 0;
}

运行结果为:

char:1
short:2
int:4
long:4
long long:8
float:4
double:8

2. 可移植数据类型

int的长度会跟随CPU的不同而发生变化,比如:

  • 16位CPU中:int默认两个字节,16位(int规定的最小值)
  • 32位CPU中:int默认四个字节,32位;

所以通常情况下使用C头文件<stdint.h>中提供的数据类型:

  • int8_t
  • uint8_t
  • int16_t
  • uint16_t
  • int32_t
  • uint32_t
  • int64_t
  • uint64_t

同时,该头文件提供了数据类型的最大最小值宏定义,如下:

/* 7.18.2.1  Limits of exact-width integer types */
#define INT8_MIN (-128)
#define INT16_MIN (-32768)
#define INT32_MIN (-2147483647 - 1)
#define INT64_MIN  (-9223372036854775807LL - 1)

#define INT8_MAX 127
#define INT16_MAX 32767
#define INT32_MAX 2147483647
#define INT64_MAX 9223372036854775807LL

#define UINT8_MAX 255
#define UINT16_MAX 65535
#define UINT32_MAX 0xffffffffU  /* 4294967295U */
#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */

3. 整数溢出问题

/**
 * CPU:64bit
 * OS:Windows10
 * IDE:Clion
 * Compiler:MinGW-64
*/

#include <stdio.h>
#include <stdint.h>

int main() {
    
    
     int8_t  a = -128, b = 127;
     uint8_t c = 0, d = 255;

     a = a - 1;
     b = b + 1;

     c = c - 1;
     d = d + 1;

    printf("a = %d, b = %d\r\n", a, b);
    printf("c = %d, d = %d\r\n", c, d);

    return 0;
}

运行结果如下:

a = 127, b = -128
c = 255, d = 0

原因:

  • 无符号整数溢出:最高位进位,因为存储空间大小限制,超出的部分直接舍弃,所以会从0开始重新计数。
  • 有符号整数溢出:数据位进位,导致符号位变为1,数据位清零,所以会从对应的最小的负数开始重新计数。

详细说明参考博文:整数在计算机中的存储

二、变量与常量

  • 变量:在程序运行过程中会改变,本质就是内存中的一段存储空间;
  • 常量:运行过程值不会改变;

1. 五种常见变量

局部变量:在函数内部定义,函数结束后变量自动销毁;

全局变量:在函数外部定义,整个文件内部都可以使用该变量,程序结束后销毁;

外部变量:使用extern修饰,表示该变量在其它文件中定义为全局变量;

静态变量:使用static修饰,表示该变量在定存中只有一份定义;

易变变量:使用volatile修饰,表示该变量是易变的,防止编译器优化;

2. 常量的两种定义方式

常量有两种:

① 使用const修饰符,作为只读变量:

const double pi = 3.1415926;

② 使用字面值:

#define PI 3.1415926

字面值的数据类型会被编译器自动识别:整数默认int,浮点数默认double,如果存不下则自动寻找更大的类型存储。

可以在数值后面加后缀,显示指出要使用的数据类型:

  • U或u:unsigned
  • L或l:long int 或者Long double
  • LL或ll:long long
  • F或f:float

三、转义字符

四、浮点数

1. 科学计数法

2. 浮点数的精度

  • float类型的精度:能表示小数点后6位;
  • doubel类型的精度:能表示小数点后10位;
/**
 * CPU:64bit
 * OS:Windows10
 * IDE:Clion
 * Compiler:MinGW-64
*/

#include <stdio.h>
#include <stdint.h>

int main() {
    
    
    float a, b;

    b = 2.0e20 + 1.0;
    a = b - 2.0e20;

    printf("a = %f\r\n", a);

    return 0;
}

运行结果为:

a = 4008175468544.000000

因为float只能存储小数点后6位的精度,所以肯定错误。

如果将2.0e20改为2.0e4,则运行结果为:

a = 1.000000

浮点数的值:2.0e4=20000,2.0e-4=0.0002

3. 浮点数的存储所带来的问题

因为浮点数不能精准的存储,所以需要在编程时注意。

eg:

/**
 * CPU:64bit
 * OS:Windows10
 * IDE:Clion
 * Compiler:MinGW-64
*/

#include <stdio.h>
#include <stdint.h>

int main() {
    
    
    float a = 99.9;

    printf("a = %f\r\n", a);

    return 0;
}

运行结果为:

a = 99.900002

五、输入输出

1. 转换说明符

常用的一些占位符如下表:

占位符 说明
%d int
%ld long
%c char
%f float
%lf double
%x int、short、long
%o int、short、long
%s 字符串
%e或者%E 使用e计数法输出浮点数
%x或者%X 无符号十六进制输出整数
%% 打印一个百分号

2. printf的用法

2.1. 基本用法

头文件:

#include <stdio.h>

用法:

printf("字符串");

printf("字符串 占位符1 占位符2", 输出参数1, 输出参数2);

2.2. printf的转换说明修饰符

%转换字符之间插入修饰符可修饰基本的转换说明。


其中可用标记如下表:

3. scanf的用法

scanf的作用:将用户从键盘输入的字符串转换为字符、字符串、整数、浮点数。

3.1. scanf的基本用法

特别注意!输入参数是变量的地址

头文件:

#include <stdio.h>
scanf("占位符", 输入参数);

//这种用法,在输入的时候必须将非占位符也输入
scanf("非占位符  占位符", 输入参数);

3.2. scanf的输入分割

scanf函数使用空白(换行符、制表符、空格)把输入分成多个字段,在依次把转换说明和字段匹配时跳过空白。

/**
 * CPU:64bit
 * OS:Windows10
 * IDE:Clion
 * Compiler:MinGW-64
*/

#include <stdio.h>

int main() {
    
    

    int a;
    float b;
    char c[20];

    scanf("%d%f%s", &a,&b, c);

    printf("a is %d, b is %.2f,c is %s\r\n", a, b, c);

    return 0;
}

运行结果如下:

1234124
1.23452
hello
a is 1234124, b is 1.23,c is hello

4. *修饰符

① 在printf中,*修饰符用来代替字段宽度,由变量指定

② 在scanf中,*修饰符表示跳过这个转换说明符。

六、运算符

1. 常用运算符

① 算术运算符:

+、-、*、/

C语言中,两个整数之间用/运算,结果也是整数。

② 关系运算符:
、>=、<、<=、!=、==

③ 逻辑运算符:
!、&&、||

④ 赋值运算符:
=、+=、-=、/=、*=

2. C语言中的真和假

  • 假:0;
  • 真:非0,除0之外都是真,一般用1表示;

3. 运算符优先级(非常重要)

算术 > 关系 > 逻辑 > 赋值

4. 其它运算符

  • sizeof运算符:返回结果是size_t类型(无符号整型,由编译器使用typedef替换为基本数据类型,在stddef.h中定义,包含在stdio.h里)
  • 求模运算符:%(只能用于整数、不能用于浮点数)
  • 自增运算符:++(分为前缀和后缀)
  • 自减运算符:–(分为前缀和后缀)
  • 三目运算符:?:
  • 位运算符:&、|、~、^、<<、>>

七、流程控制

if…else分支结构

switch…case分支结构

特别注意!case之后的标号只允许字面常量,且是整型。(变量、const只读变量、浮点数都是错误的)。

while循环结构

for循环结构

do…while循环结构

八、函数

函数是C语言的基本单位。

1. 函数声明

函数返回值类型  函数名(函数参数列表);

2. 函数定义

函数返回值类型  函数名(函数参数列表)
{
    
    
	函数主体;

	return 返回值;
}

九、数组

1. 数组的作用

解决同类型数据的存储问题。

2. 一维数组

① 定义数组:

<数据类型> <数组名>[数组中元素个数];

② 初始化数组

完全初始化:

int a[5] = {
    
    1,2,3,4,5};

不完全初始化,未被初始化的元素为0:

int a[5] = {
    
    1,2,3};

不初始化,所有元素都是垃圾值

int a[5];

清零:

//原理:第一个元素初始化为0,属于不完全初始化,所以全部为0
int a[5] = {
    
    0};

eg:

/**
 * CPU:64bit
 * OS:Windows10
 * IDE:Clion
 * Compiler:MinGW-64
*/

#include <stdio.h>
#include <stdint.h>

int main() {
    
    

    int a[5];
    int i;

    for (i = 0; i < 5; i++) {
    
    
        printf("%d ", a[i]);
    }

    printf("\r\n");

    return 0;
}

运行结果为:

8 0 73 0 1647344

③ 数组可以进行的操作:

  • 遍历
  • 赋值
  • 排序
  • 求最大值/最小值
  • 倒置
  • 查找
  • 插入
  • 删除

3. 二维数组

① 定义:

//一个3行4列的二维数组
int a[3][4];

② 初始化
整体赋值:

int a[3][4] = {
    
    1,2,3,4,5,6,7,8,9,10,11,12};

整体赋值的另外一种写法:

int a[3][4] = {
    
    
				{
    
    1,2,3},
				{
    
    4,5,6},
				{
    
    7,8,9},
				{
    
    10,11,12}
			};

③ 访问(按下标):

a[i][j]

④ 二维数组的操作:

  • 排序
  • 矩阵操作

4. 多维数组的本质

物理内存是线性连续的,所以多维数组本质并不存在。

3行4列的二维数组,本质上是3个元素一维数组,只不过每个元素也是含有4个小元素的一维数组。

十、static关键字

static关键字表示静态的,可以用来修改变量和函数。

1. static静态变量

static关键字修饰变量后,表示该变量是静态的,无论定义多少次,在内存中只有一份

比如下面的示例:

#include <stdio.h>

int test(void)
{
    
    
    int ret;
    static int id = 0;

    ret = id++;

    return ret;
}

int main()
{
    
    
    int id;

    for (int i = 0; i < 10; i++) {
    
    
        id = test();
        printf("id =  %d\r\n", id);
    }

    return 0;
}

运行结果为:

id =  0
id =  1
id =  2
id =  3
id =  4
id =  5
id =  6
id =  7
id =  8
id =  9

2. static静态函数

static修饰静态函数,表示此函数只能在本文件中使用。

猜你喜欢

转载自blog.csdn.net/Mculover666/article/details/108533501