0.0 漫画C语言计算机基础 - 从二进制开始认识计算机
🎯 学习目标
- 理解二进制与计算机的关系
- 掌握C语言基础语法和内存管理
- 了解计算机底层工作原理
- 建立编程思维基础
📖 故事开始
小明: “老王,为什么学Java之前要先学C语言?直接学Java不行吗?”
架构师老王: “哈哈,这就像学武功一样,C语言是内功心法,Java是招式套路。没有扎实的内功,招式再花哨也不堪一击!”
小明: “那计算机到底是怎么工作的呢?”
架构师老王: “一切都要从二进制说起…”
🔢 第一章:二进制世界的奥秘
1.1 为什么是二进制?
架构师老王: “计算机只认识两种状态:有电(1)和没电(0)。就像开关一样,要么开,要么关。”
十进制 → 二进制转换
10 → 1010
25 → 11001
255 → 11111111
二进制运算:
1 + 1 = 10 (进位)
1010 + 0011 = 1101
1.2 数据在内存中的存储
#include <stdio.h>
int main() {
int num = 42;
char ch = 'A';
float pi = 3.14f;
printf("整数 %d 的内存地址: %p\n", num, &num);
printf("字符 %c 的ASCII码: %d\n", ch, ch);
printf("浮点数 %.2f 占用字节: %lu\n", pi, sizeof(pi));
// 查看内存中的二进制表示
unsigned char *ptr = (unsigned char*)#
printf("整数42的二进制存储: ");
for(int i = 0; i < sizeof(int); i++) {
for(int j = 7; j >= 0; j--) {
printf("%d", (ptr[i] >> j) & 1);
}
printf(" ");
}
printf("\n");
return 0;
}
小明: “原来数据在内存中都是以二进制形式存储的!”
💾 第二章:内存管理的艺术
2.1 栈与堆的区别
架构师老王: “内存就像一个大仓库,栈区像快递柜,堆区像大仓库。”
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void stack_example() {
// 栈内存 - 自动管理
int local_var = 100; // 存储在栈上
char buffer[256]; // 栈上的数组
printf("栈变量地址: %p\n", &local_var);
printf("栈数组地址: %p\n", buffer);
} // 函数结束,栈内存自动释放
void heap_example() {
// 堆内存 - 手动管理
int *heap_var = malloc(sizeof(int)); // 在堆上分配
char *heap_str = malloc(100); // 动态分配字符串
if (heap_var && heap_str) {
*heap_var = 200;
strcpy(heap_str, "Hello, Heap!");
printf("堆变量值: %d, 地址: %p\n", *heap_var, heap_var);
printf("堆字符串: %s, 地址: %p\n", heap_str, heap_str);
// 必须手动释放
free(heap_var);
free(heap_str);
}
}
int main() {
printf("=== 栈内存示例 ===\n");
stack_example();
printf("\n=== 堆内存示例 ===\n");
heap_example();
return 0;
}
2.2 指针的威力与危险
#include <stdio.h>
// 指针基础操作
void pointer_basics() {
int value = 42;
int *ptr = &value; // 指针指向value的地址
int **double_ptr = &ptr; // 二级指针
printf("值: %d\n", value);
printf("地址: %p\n", &value);
printf("指针值: %p\n", ptr);
printf("指针指向的值: %d\n", *ptr);
printf("二级指针指向的指针的值: %d\n", **double_ptr);
}
// 数组与指针
void array_pointer() {
int arr[] = {
1, 2, 3, 4, 5};
int *p = arr; // 数组名就是指向首元素的指针
printf("数组遍历 - 下标方式:\n");
for(int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
printf("\n数组遍历 - 指针方式:\n");
for(int i = 0; i < 5; i++) {
printf("*(p+%d) = %d\n", i, *(p + i));
}
}
// 函数指针
int add(int a, int b) {
return a + b; }
int multiply(int a, int b) {
return a * b; }
void function_pointer() {
int (*operation)(int, int); // 函数指针声明
operation = add;
printf("5 + 3 = %d\n", operation(5, 3));
operation = multiply;
printf("5 * 3 = %d\n", operation(5, 3));
}
int main() {
pointer_basics();
printf("\n");
array_pointer();
printf("\n");
function_pointer();
return 0;
}
小明: “指针这么强大,但是也很容易出错啊!”
架构师老王: “没错!指针是C语言的精髓,也是最容易出bug的地方。这就是为什么Java要引入垃圾回收机制。”