- C编程教程
- C - 首页
- C语言基础
- C - 概述
- C - 特性
- C - 历史
- C - 环境搭建
- C - 程序结构
- C - Hello World
- C - 编译过程
- C - 注释
- C - 词法单元
- C - 关键字
- C - 标识符
- C - 用户输入
- C - 基本语法
- C - 数据类型
- C - 变量
- C - 整数提升
- C - 类型转换
- C - 类型强制转换
- C - 布尔值
- C语言中的常量和字面量
- C - 常量
- C - 字面量
- C - 转义序列
- C - 格式说明符
- C语言中的运算符
- C - 运算符
- C - 算术运算符
- C - 关系运算符
- C - 逻辑运算符
- C - 位运算符
- C - 赋值运算符
- C - 一元运算符
- C - 自增和自减运算符
- C - 三元运算符
- C - sizeof运算符
- C - 运算符优先级
- C - 其他运算符
- C语言中的决策
- C - 决策
- C - if语句
- C - if...else语句
- C - 嵌套if语句
- C - switch语句
- C - 嵌套switch语句
- C语言中的循环
- C - 循环
- C - while循环
- C - for循环
- C - do...while循环
- C - 嵌套循环
- C - 死循环
- C - break语句
- C - continue语句
- C - goto语句
- C语言中的函数
- C - 函数
- C - 主函数
- C - 按值调用函数
- C - 按引用调用函数
- C - 嵌套函数
- C - 变参函数
- C - 用户自定义函数
- C - 回调函数
- C - 返回语句
- C - 递归
- C语言中的作用域规则
- C - 作用域规则
- C - 静态变量
- C - 全局变量
- C语言中的数组
- C - 数组
- C - 数组的特性
- C - 多维数组
- C - 将数组传递给函数
- C - 从函数返回数组
- C - 变长数组
- C语言中的指针
- C - 指针
- C - 指针和数组
- C - 指针的应用
- C - 指针运算
- C - 指针数组
- C - 指向指针的指针
- C - 将指针传递给函数
- C - 从函数返回指针
- C - 函数指针
- C - 指向数组的指针
- C - 指向结构体的指针
- C - 指针链
- C - 指针与数组的区别
- C - 字符指针和函数
- C - 空指针
- C - void指针
- C - 悬空指针
- C - 解引用指针
- C - 近指针、远指针和巨大指针
- C - 指针数组的初始化
- C - 指针与多维数组的区别
- C语言中的字符串
- C - 字符串
- C - 字符串数组
- C - 特殊字符
- C语言中的结构体和联合体
- C - 结构体
- C - 结构体和函数
- C - 结构体数组
- C - 自引用结构体
- C - 查找表
- C - 点(.)运算符
- C - 枚举(enum)
- C - 结构体填充和打包
- C - 嵌套结构体
- C - 匿名结构体和联合体
- C - 联合体
- C - 位域
- C - typedef
- C语言中的文件处理
- C - 输入和输出
- C - 文件I/O(文件处理)
- C预处理器
- C - 预处理器
- C - 编译指示
- C - 预处理器运算符
- C - 宏
- C - 头文件
- C语言中的内存管理
- C - 内存管理
- C - 内存地址
- C - 存储类
- 其他主题
- C - 错误处理
- C - 可变参数
- C - 命令执行
- C - 数学函数
- C - static关键字
- C - 随机数生成
- C - 命令行参数
- C编程资源
- C - 问答
- C - 快速指南
- C - 速查表
- C - 有用资源
- C - 讨论
C语言中的内存地址
C语言中的内存地址
在C语言中声明变量时,会为其分配一个内存地址。C编译器将变量的值存储在内存的不同段中。
内存段
C程序的不同元素存储在计算机内存的不同段中,这些段包括:
- 代码段 − 代码段,也称为代码段或简称为文本,是程序的一个部分,用于存储C程序的目标版本。
- 已初始化数据段 − 程序员初始化的全局变量和静态变量在已初始化数据段中分配内存。
- 未初始化数据段 − 未初始化数据段也称为bss(代表block started by symbol)。程序加载时会为此段分配内存。在C程序执行之前,内核会将bss中的所有数据初始化为算术“0”,并将指针初始化为空指针。
- 栈 − 栈是一种LIFO(后进先出)数据结构。栈段存储局部变量的值和传递给函数的参数的值。它还维护函数调用返回的指针。
- 堆 − 堆用于在运行时分配内存。所有执行动态内存分配的函数都与堆相关。
访问内存地址
可以通过取地址(&)运算符访问或指定C语言中的内存地址。要使用printf()函数打印内存地址,需要使用%p格式说明符。
语法
以下是访问内存地址的语法:
&variable_name
示例
在下面的示例中,我们声明两个变量并打印它们的内存地址:
#include <stdio.h> int main() { // Declaring two variables int a; int b; // Accessing their memory // addresses and print them printf("Memory address of a is %p\n", &a); printf("Memory address of b is %p\n", &b); return 0; }
C编译器如何分配内存?
内存可以被认为是一个字节数组,每个地址都是数组中的一个索引,并保存1个字节。
在C程序中声明变量时,C编译器会根据大小需求(取决于类型)为其分配一个随机内存位置。
声明一个int变量时:
int x = 10;
编译器会在随机字节地址中赋值。由于int类型需要4个字节,因此会为此预留接下来的四个地址。
C允许您找出已为变量分配了哪个地址。您可以使用%p格式说明符来打印内存位置的十六进制地址。
char x = 'A'; printf ("address of x: %p\n", &x);
这将打印“x”的十六进制地址:
Address of x: 000000000061FE1F
示例
C语言中的数组是连续的内存区域,用于保存相同数据类型(int、long、*char等)的多个值。
#include <stdio.h> int main() { // initialize an array of ints int numbers[5] = {1,2,3,4,5}; int i = 0; // print the address of the array variable printf("numbers = %p\n", numbers); // print addresses of each array index do { printf("numbers[%u] = %p\n", i, (void *)(&numbers[i])); i++; } while(i < 5); // print the size of the array printf("sizeof(numbers) = %lu\n", sizeof(numbers)); }
输出
运行此代码时,将产生以下输出:
numbers = 0x7fff0815c0e0 numbers[0] = 0x7fff0815c0e0 numbers[1] = 0x7fff0815c0e4 numbers[2] = 0x7fff0815c0e8 numbers[3] = 0x7fff0815c0ec numbers[4] = 0x7fff0815c0f0 sizeof(numbers) = 20
广告