第2讲:C语言数据类型和变量

第2讲:C语言数据类型和变量

留个关注支持一下博主吧,持续产出更多优质内容

--主讲人:老王爱玩车

本文所有 C 代码块都是完整程序,可直接保存为 .c 文件编译运行。

在 VS2022 中运行快捷键:Ctrl + F5

如果代码中使用了 scanf,文件开头已加 #define _CRT_SECURE_NO_WARNINGS 1,用于关闭 VS 的安全警告;其他编译器可忽略。

#define _CRT_SECURE_NO_WARNINGS 1 在.c文件第一行添加一句即可,没必要写一段程序就添加一句。

带有" * " 衔接多了解即可,后续会详细讲解


目录

  1. 学习目标
  2. 数据类型
  3. C语言内置数据类型
  4. sizeof:C语言的数据尺子(重点扩充)
  5. [signedunsigned](#signed 与 unsigned)
  6. 数据类型的取值范围
  7. 变量:创建、初始化、作用域
  8. 算术操作符:+-*/%
  9. [赋值操作符:= 和复合赋值](#赋值操作符:= 和复合赋值)
  10. 单目操作符:++--+-
  11. 强制类型转换
  12. [printfscanf](#printf 与 scanf)
  13. 课堂练习
  14. 本讲小结


1. 学习目标

学完本讲,你应该能够:

  • 了解 C 语言常见内置数据类型,知道它们的大致用途;
  • 使用 sizeof 计算类型、变量、数组、表达式所占的字节数;
  • 区分 signedunsigned,理解无符号数的特点;
  • 正确创建、初始化变量,理解全局变量和局部变量的区别;
  • 熟练使用算术操作符、赋值操作符、单目操作符;
  • 正确使用 printf 输出、scanf 输入;
  • 能看懂并写出可直接运行的小程序。

2. 数据类型

  • 数据在内存中怎么存;
  • 不同类型的数据占多少空间;
  • 程序怎么被编译、链接、运行;
  • 变量怎么组织、函数怎么调用。

C 语言提供了丰富的数据类型来描述生活中的数据:

  • 整数:shortintlonglong long
  • 字符:char
  • 小数:floatdoublelong double
  • 真假:_Bool / bool

所谓"类型",就是相似数据所拥有的共同特征。

编译器只有知道数据的类型,才知道怎么操作数据。


3. C语言内置数据类型

3.1 字符型

c 复制代码
char              // 字符型
signed char       // 有符号字符型
unsigned char     // 无符号字符型

字符型用来存储单个字符,例如 'A''0''\n'

在内存中,字符实际存储的是对应的编码值,常见的是 ASCII 编码。

3.2 整型

c 复制代码
short [int]
[signed] short [int]
unsigned short [int]

int
[signed] int
unsigned int

long [int]
[signed] long [int]
unsigned long [int]

long long [int]          // C99 引入
[signed] long long [int]
unsigned long long [int]

整型用来存储整数。

不同整型的主要区别是:占用的内存大小不同,能表示的数值范围不同。

3.3 浮点型

c 复制代码
float
double
long double

浮点型用来存储小数。

float 精度较低,double 精度较高,long double 精度通常更高。

3.4 布尔类型

C 语言原来没有专门的布尔类型,而是用整数 0 表示假,非零值表示真。

C99 引入了 _Bool 类型,专门表示真假。

使用 booltruefalse 需要包含 <stdbool.h>

完整程序演示:

c 复制代码
#include <stdio.h>
#include <stdbool.h>

int main(void)
{
    bool flag = true;

    if (flag)
    {
        printf("i like C\n");
    }

    return 0;
}

运行结果:

text 复制代码
i like C

4. sizeof:C语言的数据尺子

4.1 sizeof 是什么

sizeof 是 C 语言中的一个 关键字 ,同时也是 单目操作符

它的作用是:计算某个类型、变量或表达式在内存中占用的字节数。

语法有三种常见形式:

c 复制代码
sizeof(类型)
sizeof(变量)
sizeof 表达式

注意:

  • sizeof 不是函数,虽然写法像函数;
  • sizeof 的单位是 字节
  • 如果操作数是类型,括号不能省略;
  • 如果操作数是变量或表达式,括号可以省略;
  • sizeof 在编译期间就能确定大小(变长数组除外)。

完整程序:三种写法

c 复制代码
#include <stdio.h>

int main(void)
{
    int a = 10;

    printf("%zu\n", sizeof(int));      // 类型,必须加括号
    printf("%zu\n", sizeof(a));        // 变量,可以加括号
    printf("%zu\n", sizeof a);         // 变量,可以省略括号
    printf("%zu\n", sizeof(3 + 3.5));  // 表达式

    return 0;
}

在 64 位环境下,常见输出:

text 复制代码
4
4
4
8

说明:3 + 3.5 中,3int3.5double,运算时 3 会转换为 double,所以表达式类型是 double,大小为 8 字节。


4.2 sizeof 的返回类型和打印占位符

sizeof 的返回值类型是 size_t

size_t 是一种无符号整数类型,具体是 unsigned int 还是 unsigned long,由系统决定。

打印 sizeof 的结果,推荐使用 %zu

部分老教程或环境中也会使用 %zd%lu%llu,但 %zu 更标准。

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    printf("sizeof(char)   = %zu\n", sizeof(char));
    printf("sizeof(short)  = %zu\n", sizeof(short));
    printf("sizeof(int)    = %zu\n", sizeof(int));
    printf("sizeof(long)   = %zu\n", sizeof(long));
    printf("sizeof(float)  = %zu\n", sizeof(float));
    printf("sizeof(double) = %zu\n", sizeof(double));

    return 0;
}

在 VS2022 x64 环境下,常见输出:

text 复制代码
sizeof(char)   = 1
sizeof(short)  = 2
sizeof(int)    = 4
sizeof(long)   = 4
sizeof(float)  = 4
sizeof(double) = 8

注意:不同平台、不同编译器,long、指针等类型的大小可能不同。

所以 sizeof 的结果要以实际编译环境为准。


4.3 sizeof 作用于变量和表达式

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    int a = 10;
    double d = 3.14;
    char c = 'A';

    printf("sizeof(a)     = %zu\n", sizeof(a));
    printf("sizeof(d)     = %zu\n", sizeof(d));
    printf("sizeof(c)     = %zu\n", sizeof(c));
    printf("sizeof(a + d) = %zu\n", sizeof(a + d));
    printf("sizeof(c + 1) = %zu\n", sizeof(c + 1));

    return 0;
}

常见输出:

text 复制代码
sizeof(a)     = 4
sizeof(d)     = 8
sizeof(c)     = 1
sizeof(a + d) = 8
sizeof(c + 1) = 4

说明:

  • a + d 中,a 会转换为 double,所以结果是 double 大小;
  • c + 1 中,char 会进行整型提升,通常提升为 int,所以结果是 int 大小。

4.4 sizeof 中的表达式不计算

这是 sizeof 最经典的特性之一:

sizeof 后面的表达式不会真实参与运算,它只根据表达式的类型来推导大小。

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    short s = 2;
    int b = 10;

    printf("%zu\n", sizeof(s = b + 1));
    printf("s = %d\n", s);

    return 0;
}

运行结果:

text 复制代码
2
s = 2

解释:

  • s = b + 1 的结果类型是 short,所以 sizeof 得到 2;
  • 但这个赋值表达式在运行期间并不会真正执行;
  • 所以 s 仍然是 2,而不是 11。

*4.5 sizeof 与数组

sizeof 可以用来计算整个数组的大小,也可以计算数组元素的大小,从而求出元素个数。

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    int arr[10] = {0};

    printf("sizeof(arr)    = %zu\n", sizeof(arr));
    printf("sizeof(arr[0]) = %zu\n", sizeof(arr[0]));
    printf("元素个数       = %zu\n", sizeof(arr) / sizeof(arr[0]));

    return 0;
}

int 为 4 字节的环境下,输出:

text 复制代码
sizeof(arr)    = 40
sizeof(arr[0]) = 4
元素个数       = 10

常见求数组元素个数的写法:

c 复制代码
int count = sizeof(arr) / sizeof(arr[0]);

注意:这种写法只适用于真正在数组定义所在作用域内。

如果数组作为函数参数传递,它会退化为指针,不能再这样求元素个数。

完整程序:数组传参后退化为指针

c 复制代码
#include <stdio.h>

void func(int arr[10])
{
    printf("func 中 sizeof(arr) = %zu\n", sizeof(arr));
}

int main(void)
{
    int arr[10] = {0};

    printf("main 中 sizeof(arr) = %zu\n", sizeof(arr));
    func(arr);

    return 0;
}

注:仅作参考后续会详细讲解,这里不再过多赘述。


*4.6 sizeof 与字符串、strlen 的区别

sizeofstrlen 经常被混淆。

  • sizeof:计算类型或变量占用的总字节数,包含字符串末尾的 \0
  • strlen:计算字符串长度,遇到 \0 停止,不包含 \0
  • sizeof 是操作符,strlen 是库函数,需要包含 <string.h>

完整程序:

c 复制代码
#include <stdio.h>
#include <string.h>

int main(void)
{
    char s1[] = "hello";
    char *s2 = "hello";

    printf("sizeof(s1) = %zu\n", sizeof(s1));
    printf("strlen(s1) = %zu\n", strlen(s1));
    printf("sizeof(s2) = %zu\n", sizeof(s2));
    printf("strlen(s2) = %zu\n", strlen(s2));

    return 0;
}
复制代码
解释:

- `s1` 是字符数组,内容为 `'h','e','l','l','o','\0'`,所以 `sizeof(s1)` 是 6;
- `strlen(s1)` 只计算到 `\0` 前,所以是 5;
- `s2` 是指针,`sizeof(s2)` 是指针大小,64 位下通常是 8;
- `strlen(s2)` 仍然是 5。

---

### *4.7 `sizeof` 与指针

指针的大小与平台有关:

- 32 位平台:指针通常 4 字节;
- 64 位平台:指针通常 8 字节。

完整程序:

```c
#include <stdio.h>

int main(void)
{
    int *p = NULL;
    char *c = NULL;
    double *d = NULL;

    printf("sizeof(int *)    = %zu\n", sizeof(p));
    printf("sizeof(char *)   = %zu\n", sizeof(c));
    printf("sizeof(double *) = %zu\n", sizeof(d));

    return 0;
}

注意:不管指针指向什么类型,同一平台下指针大小通常相同。


*4.8 sizeof 与结构体

sizeof 也可以计算结构体的大小。

但结构体大小可能涉及内存对齐,不同平台结果可能不同。

完整程序:

c 复制代码
#include <stdio.h>

struct S
{
    char c;
    int i;
};

int main(void)
{
    printf("sizeof(struct S) = %zu\n", sizeof(struct S));

    return 0;
}

解释:char c 占 1 字节,但为了对齐 int i,后面可能填充 3 字节,然后 int i 占 4 字节,总共 8 字节。

注:不必深究,后面会详细讲解。


4.9 sizeof 易错点总结

  1. sizeof 不是函数,是操作符

    可以写 sizeof a,但不能写 sizeof int 这种省略括号的形式。

  2. sizeof 中的表达式不计算

    sizeof(i++) 不会让 i 自增。

  3. sizeof 返回无符号整数

    和负数比较时容易出现陷阱。

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    if (sizeof(int) > -1)
        printf("yes\n");
    else
        printf("no\n");

    return 0;
}

运行结果:

text 复制代码
no

原因:sizeof(int) 是无符号类型,-1 在比较时会转换为无符号整数中的最大值,所以 sizeof(int) > -1 为假。

  1. 数组和指针不要混淆

    数组名在 sizeof 中代表整个数组;

    数组作为函数参数后,退化为指针。

  2. 字符串字面量包含 \0

    sizeof("hello") 是 6,不是 5。

  3. sizeof 不能计算函数类型

    例如 sizeof(main) 是错误的。

7.* 变长数组是例外

C99 的变长数组,sizeof 可能在运行期间计算。初学阶段了解即可。


5. signedunsigned

signed 表示类型带有正负号,包含负值。

unsigned 表示类型不带正负号,只能表示零和正整数。


对于 int 类型,默认是带有正负号的,也就是说:

c 复制代码
int a;          // 等价于 signed int a;
signed int b;   // 也可以写
unsigned int c; // 无符号整型

unsigned int 中的 int 可以省略:

c 复制代码
unsigned a;

字符类型 char 也可以设置 signedunsigned

c 复制代码
signed char c;    // 范围通常为 -128 到 127
unsigned char c;  // 范围通常为 0 到 255

注意:C 语言规定 char 默认是否带正负号由当前系统决定。

也就是说,char 不等同于 signed char,它可能是 signed char,也可能是 unsigned char

这一点与 int 不同,int 就是等同于 signed int


完整程序:查看 limits.h 中的极值

c 复制代码
#include <stdio.h>
#include <limits.h>

int main(void)
{
    printf("SHRT_MIN  = %d\n", SHRT_MIN);
    printf("SHRT_MAX  = %d\n", SHRT_MAX);
    printf("USHRT_MAX = %u\n", USHRT_MAX);
    printf("INT_MIN   = %d\n", INT_MIN);
    printf("INT_MAX   = %d\n", INT_MAX);

    return 0;
}

运行结果示例:

text 复制代码
SHRT_MIN  = -32768
SHRT_MAX  = 32767
USHRT_MAX = 65535
INT_MIN   = -2147483648
INT_MAX   = 2147483647

6. 数据类型的取值范围

为什么要有很多整型?

因为每种数据类型都有自己的取值范围,也就是能存储的最大值和最小值。

如果要查看当前系统上不同数据类型的极限值:

  • 整型:查看 limits.h
  • 浮点型:查看 float.h

为了代码可移植性,需要知道某种整数类型的极限值时,应尽量使用这些常量:

  • SCHAR_MINSCHAR_MAX
  • SHRT_MINSHRT_MAX
  • INT_MININT_MAX
  • LONG_MINLONG_MAX

7. 变量:创建、初始化、作用域

7.1 变量的创建

C 语言中,经常变化的值称为变量,不变的值称为常量。

变量创建的语法:

c 复制代码
数据类型 变量名;

例如:

c 复制代码
int age;
char ch;
double weight;

创建时给初始值,叫初始化:

c 复制代码
int age = 18;
char ch = 'w';
double weight = 48.0;
unsigned int height = 100;

7.2 全局变量和局部变量

  • 在大括号外部定义的变量是全局变量;
  • 在大括号内部定义的变量是局部变量;
  • 局部变量和全局变量同名时,局部变量优先使用。

完整程序:变量作用域演示

c 复制代码
#include <stdio.h>

int global = 2023;   // 全局变量

int main(void)
{
    int local = 2018;    // 局部变量
    int global = 10;     // 局部变量,遮蔽全局变量

    printf("local  = %d\n", local);
    printf("global = %d\n", global);

    return 0;
}

运行结果:

text 复制代码
local  = 2018
global = 10

全局变量和局部变量在内存中的存储位置:

  • 局部变量:栈区
  • 全局变量:静态区
  • 堆区:动态内存管理,后续课程介绍

8. 算术操作符:+-*/%

算术操作符:

c 复制代码
+  -  *  /  %

它们都是双目操作符,有两个操作数。

8.1 加法和减法

c 复制代码
int x = 4 + 22;
int y = 61 - 23;

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    int x = 4 + 22;
    int y = 61 - 23;

    printf("x = %d\n", x);
    printf("y = %d\n", y);

    return 0;
}

8.2 乘法

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    int num = 5;
    printf("%d\n", num * num);
    return 0;
}

运行结果:

text 复制代码
25

8.3 除法

除号两端如果都是整数,执行的是整数除法,结果也是整数,小数部分会被丢弃。

完整程序:整数除法和浮点数除法

c 复制代码
#include <stdio.h>

int main(void)
{
    int x = 6 / 4;
    float y = 6 / 4;
    float z = 6.0 / 4;

    printf("x = %d\n", x);
    printf("y = %f\n", y);
    printf("z = %f\n", z);

    return 0;
}

运行结果:

text 复制代码
x = 1
y = 1.000000
z = 1.500000

如果希望得到浮点数结果,两个运算数必须至少有一个浮点数。

完整程序:整数除法陷阱

c 复制代码
#include <stdio.h>

int main(void)
{
    int score = 5;

    printf("%d\n", (score / 20) * 100);
    printf("%.1f\n", (score / 20.0) * 100);

    return 0;
}

运行结果:

text 复制代码
0
25.0

8.4 取模 %

% 表示求模运算,即返回两个整数相除的余值。

它只能用于整数,不能用于浮点数。

完整程序:正负数取模

c 复制代码
#include <stdio.h>

int main(void)
{
    printf("%d\n", 11 % -5);
    printf("%d\n", -11 % -5);
    printf("%d\n", -11 % 5);

    return 0;
}

运行结果:

text 复制代码
1
-1
-1

规则:结果的正负号由第一个运算数的正负号决定。


9. 赋值操作符:= 和复合赋值

在变量创建时给初始值叫初始化:

c 复制代码
int a = 100;

在变量创建好后,再给一个值,叫赋值:

c 复制代码
a = 200;

9.1 连续赋值

c 复制代码
int a = 3;
int b = 5;
int c = 0;

c = b = a + 3;   // 从右向左赋值

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    int a = 3;
    int b = 5;
    int c = 0;

    c = b = a + 3;

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

    return 0;
}

运行结果:

text 复制代码
a = 3
b = 6
c = 6

建议拆开写,便于调试:

可以看博主的VS实用调试技巧一文,里面有详细的调试技巧。

c 复制代码
b = a + 3;
c = b;

9.2 复合赋值符

常见复合赋值符:

c 复制代码
+=  -=  *=  /=  %=

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    int a = 10;

    a += 3;   // a = a + 3
    a -= 2;   // a = a - 2
    a *= 2;   // a = a * 2
    a /= 4;   // a = a / 4
    a %= 4;   // a = a % 4

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

    return 0;
}

运行结果:

text 复制代码
a = 1

10. 单目操作符:++--+-

单目操作符只有一个操作数。

10.1 前置 ++ 和后置 ++

  • 前置 ++:先 +1,后使用;
  • 后置 ++:先使用,后 +1

完整程序:自增自减演示

c 复制代码
#include <stdio.h>

int main(void)
{
    int a = 10;
    int b = ++a;
    printf("前置++: a = %d, b = %d\n", a, b);

    a = 10;
    b = a++;
    printf("后置++: a = %d, b = %d\n", a, b);

    a = 10;
    b = --a;
    printf("前置--: a = %d, b = %d\n", a, b);

    a = 10;
    b = a--;
    printf("后置--: a = %d, b = %d\n", a, b);

    return 0;
}

运行结果:

text 复制代码
前置++: a = 11, b = 11
后置++: a = 11, b = 10
前置--: a = 9, b = 9
后置--: a = 9, b = 10

10.2 单目 +-

+ 是正号,对正负值没有影响,可以省略。

- 是负号,用来改变一个值的正负号。

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    int a = 10;
    int b = -a;
    int c = -10;

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

    a = -10;
    b = -a;
    printf("b = %d\n", b);

    return 0;
}

运行结果:

text 复制代码
b = -10, c = -10
b = 10

11. 强制类型转换

强制类型转换的语法:

c 复制代码
(类型)

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    double pi = 3.14159;
    int a = (int)pi;   // 只取整数部分

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

    return 0;
}

运行结果:

text 复制代码
pi = 3.141590
a  = 3

强制类型转换只取整数部分,不会四舍五入。

俗话说,强扭的瓜不甜,能不用就不用。


12. printfscanf

12.1 printf 基本用法

printf() 的作用是把文本输出到屏幕。

它不会自动换行,需要手动添加 \n

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    printf("Hello World\n");
    printf("Hello\nWorld\n");

    return 0;
}

12.2 占位符

常见占位符:

占位符 含义
%c 字符
%d 十进制整数
%f 浮点数
%s 字符串
%u 无符号整数
%x 十六进制整数
%p 指针
%zu size_t 类型
%% 输出一个百分号

占位符:顾名思义他的作用就是占位,告诉编译器,这个位置我要以什么样的格式输出一个东西


完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    printf("There are %d apples\n", 3);
    printf("%s will come tonight\n", "zhangsan");
    printf("%s says it is %d o'clock\n", "lisi", 21);

    return 0;
}

12.3 输出格式控制

c 复制代码
#include <stdio.h>

int main(void)
{
    printf("[%5d]\n", 123);
    printf("[%-5d]\n", 123);
    printf("[%12f]\n", 123.45);
    printf("[%+d]\n", 12);
    printf("[%+d]\n", -12);
    printf("[%.2f]\n", 0.5);
    printf("[%6.2f]\n", 0.5);
    printf("[%*.*f]\n", 6, 2, 0.5);
    printf("[%.5s]\n", "hello world");

    return 0;
}

运行结果:

text 复制代码
[  123]
[123  ]
[      123.450000]
[+12]
[-12]
[0.50]
[  0.50]
[  0.50]
[hello]

12.4 scanf 基本用法

scanf() 用于读取键盘输入。

变量前面必须加 &(指针变量除外),因为 scanf() 需要的是地址。


完整程序:

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main(void)
{
    int score = 0;

    printf("请输入成绩: ");
    scanf("%d", &score);
    printf("成绩是: %d\n", score);

    return 0;
}

运行示例:

text 复制代码
请输入成绩: 100
成绩是: 100

12.5 scanf 的返回值

scanf() 返回成功读取的变量个数。

如果没有读取任何项,或匹配失败,返回 0

如果读取错误或遇到文件结尾,返回 EOF,通常为 -1

完整程序:

c 复制代码
#include <stdio.h>

int main(void)
{
    int a = 0;
    int b = 0;
    float f = 0.0f;

    int r = scanf("%d %d %f", &a, &b, &f);

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

    return 0;
}

输入:

text 复制代码
1 2 3.14

输出:

text 复制代码
a = 1, b = 2, f = 3.140000
r = 3

12.6 scanf 常见占位符

  • %c:字符,不忽略空白字符
  • %d:整数
  • %ffloat 类型浮点数
  • %lfdouble 类型浮点数
  • %s:字符串,遇到空白字符停止
  • %[]:指定字符集合

完整程序:%s 指定最大长度

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main(void)
{
    char name[11];

    printf("请输入姓名(最多10个字符): ");
    scanf("%10s", name);
    printf("name = %s\n", name);

    return 0;
}

12.7 赋值忽略符 *

完整程序:解析日期

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main(void)
{
    int year = 0;
    int month = 0;
    int day = 0;

    printf("请输入日期(如 2026-09-13 或 2026/09/13): ");
    scanf("%d%*c%d%*c%d", &year, &month, &day);

    printf("%d %d %d\n", year, month, day);

    return 0;
}

%*c 表示读取一个字符但不保存,用于忽略 -/


13. 课堂练习

练习1:类型长度判断

以下程序在常见 64 位环境下输出什么?

c 复制代码
#include <stdio.h>

int main(void)
{
    printf("%zu\n", sizeof(char));
    printf("%zu\n", sizeof(short));
    printf("%zu\n", sizeof(int));
    printf("%zu\n", sizeof(long long));
    printf("%zu\n", sizeof(float));
    printf("%zu\n", sizeof(double));

    return 0;
}

参考答案:

text 复制代码
1
2
4
8
4
8

练习2:sizeof 数组与元素个数

以下程序在 int 为 4 字节的环境下输出什么?

c 复制代码
#include <stdio.h>

int main(void)
{
    int arr[5] = {1, 2, 3, 4, 5};

    printf("%zu\n", sizeof(arr));
    printf("%zu\n", sizeof(arr[0]));
    printf("%zu\n", sizeof(arr) / sizeof(arr[0]));

    return 0;
}

参考答案:

text 复制代码
20
4
5

练习3:sizeofstrlen

以下程序在 64 位环境下输出什么?

c 复制代码
#include <stdio.h>
#include <string.h>

int main(void)
{
    char s1[] = "hello";
    char *s2 = "hello";

    printf("%zu %zu\n", sizeof(s1), strlen(s1));
    printf("%zu %zu\n", sizeof(s2), strlen(s2));

    return 0;
}

参考答案:

text 复制代码
6 5
8 5

练习4:sizeof 表达式不计算

以下程序输出什么?

c 复制代码
#include <stdio.h>

int main(void)
{
    int i = 5;

    printf("%zu\n", sizeof(i++));
    printf("%d\n", i);

    return 0;
}

参考答案:

text 复制代码
4
5

解析:sizeof(i++) 不会执行 i++


练习5:sizeof 无符号陷阱

以下程序输出什么?

c 复制代码
#include <stdio.h>

int main(void)
{
    if (sizeof(int) > -1)
        printf("yes\n");
    else
        printf("no\n");

    return 0;
}

参考答案:

text 复制代码
no

解析:sizeof 返回无符号类型,-1 被转换为无符号最大值。


14. 本讲小结

  • C 语言数据类型包括字符型、整型、浮点型、布尔类型;
  • sizeof 是关键字,也是操作符,用来计算类型或变量所占内存大小,单位是字节;
  • sizeof 的返回值类型是 size_t,常用 %zu 打印;
  • sizeof 中的表达式不会真实参与运算;
  • 数组名在 sizeof 中代表整个数组,但数组传参后会退化为指针;
  • sizeofstrlen 不同,前者包含 \0,后者不包含;
  • signed 表示有符号,unsigned 表示无符号;
  • 变量分为全局变量和局部变量,局部变量优先;
  • 算术操作符中,整数除法会丢弃小数部分,% 只能用于整数;
  • 赋值操作符可以连续赋值,复合赋值更简洁;
  • ++-- 分前置和后置,前置先加/减,后置后加/减;
  • 强制类型转换只取整数部分,不会四舍五入;
  • printf 负责输出,scanf 负责输入,scanf 变量前通常要加 &
  • 代码要能跑起来,再逐步理解它为什么能跑起来。

后续会带来更多优质内容,各位大佬六个关注支持一下吧

相关推荐
菜鸟~noob2331 小时前
【电子战】第12篇:TDOA 定位——双曲线与等时差线【含matlab代码】
开发语言·matlab
零依赖极客1 小时前
Day 9·1 KV 也量化——q8 KV 把缓存与 decode 带宽压到一半
c语言·开发语言·arm开发·人工智能·缓存·矩阵
CoderYanger1 小时前
Java EE 进阶:2.3 JavaScript
java·开发语言·前端·javascript·css·职场和发展·java-ee
敲代码的嘎仔2 小时前
互动问答系统实战:两级评论模型、ES 搜索集成、Caffeine 多级缓存全记录
java·开发语言·数据库·elasticsearch·缓存·mybatis·高并发
yujunl2 小时前
找不到指定的SDK(“Microsoft.NET.Sdk.Web“)
开发语言
郝学胜-神的一滴2 小时前
C++11 工程级应用 12:编译期类型魔法,干掉重复与臃肿的代码
开发语言·数据结构·c++·软件工程·visual studio
个 人 练 习 生2 小时前
数据结构:排序算法详解
c语言·数据结构·经验分享·学习·算法·排序算法
m0_734571762 小时前
深入理解C++ 析构函数<四>虚析构函数
开发语言·c++