char、int、long它们各占几个字节?占几位?

本文详细介绍了C语言中的基本数据类型,包括整型、长整型、字符型、单精度浮点型、双精度浮点型、长双精度浮点型等,并提供了在不同机器上的具体位长度。此外,还附带了C语言中常用的数据类型及其位长度的对照表,以及1GB、MB、KB等单位之间的换算关系。

转自:http://wenwen.soso.com/z/q104804861.htm

整型 int 4字节
长整型 long 4字节
字符型 char 1字节
单精度 float 4字节
双精度 double 8字节
长双精度 long double 8字节

换算关系:
1GB=1024MB
1MB=1024KB
1KB=1024Byte
1Byte=8Bit
一个字节等于八个位


额外补充:

C语言基本数据类型

类型                   位长度 
char                      8
unsigned char            8
signed char               8    
int                       16
unsigned int             16
signed int                16
short int                 16
unsigned short int     16
signed short int         16
long int                  32
signed long int          32
float                     32
double                    64
long double              64

以上是16位机上的C数据类型。

在32位机子上int 为4字节

<think> 我们已知错误信息中的虚拟地址是0x1a4(十六进制),即420字节(十进制)。我们需要确定这个偏移量可能属于哪个内核结构体,并确认int型在特定体系结构中的大小。 ### 步骤1:确定基本数据类型大小 - 在Linux内核中,基本数据类型的大小与体系结构相关。例如: - `int` 类型通常为4字节(32位和64位系统) - `long` 类型的长度会根据体系结构变化(32位系统为4字节,64位系统为8字节) - 假设我们运行在常见的64位系统上,常见大小: ```c char: 1字节 short: 2字节 int: 4字节 long: 8字节 指针: 8字节 ``` ### 步骤2:分析结构体偏移 错误发生在偏移0x1a4(420)处,因此我们需要寻找包含至少420字节的结构体,且在该偏移处的成员类型可能是整型(如int)。 #### 示例:计算结构体成员偏移 假设我们有一个结构体: ```c struct example { char id[128]; // 0-127 (128字节) int count; // 128-131 long pointers[16]; // 132-131+128=259? 实际上需要对齐 }; ``` 实际计算偏移量需要考虑内存对齐(alignment)。在64位系统中,通常按照8字节对齐。 #### 使用内核内置宏确定偏移 在内核开发中,可以使用`offsetof`宏来确定结构体成员的偏移: ```c #include <linux/stddef.h> struct my_struct { char buffer[400]; int status; int config; int error_code; }; // 在代码中打印偏移 printk("error_code offset: %lu\n", offsetof(struct my_struct, error_code)); ``` ### 步骤3:定位实际结构体 要确定0x1a4具体属于哪个结构体,需要结合内核源代码和Oops信息: 1. **查看Oops日志**:通常Oops会打印调用栈和寄存器值,通过反汇编可定位代码位置 2. **分析代码上下文**:出错指令所在的函数会操作哪些结构体 3. **使用调试符号**:若有内核调试符号,可直接映射地址到结构体成员 #### 示例:通过Oops日志定位 假设Oops日志片段: ``` Call Trace: [<ffffffff81345a2c>] ? read_device+0x1c/0x50 ``` 反汇编`read_device`函数: ```bash objdump -d vmlinux | grep -A 20 'read_device>:' ``` 在反汇编代码中查找访问`0x1a4`偏移的指令,如: ``` mov 0x1a4(%rax), %eax # 从rax+0x1a4加载数据 ``` 此时寄存器rax的值就是结构体基地址(若为NULL则出错) ### 步骤4:计算结构体成员偏移 假设我们怀疑是某个结构体,例如: ```c struct device_driver { const char *name; // 8字节 (64位) int major; // 4字节 (需补齐到8字节对齐) int minor; // 4字节 char desc[256]; // 256字节 long ops[10]; // 80字节 // ... 其他成员 }; ``` 手动计算偏移: - `name`: 0-7 - `major`: 8-11, 但需要对齐到8字节,所以实际占用8-15(浪费12-15) - `minor`: 16-19 -> 对齐后占用16-23 - `desc`: 24-279 - `ops`: 280-359 此时偏移420(0x1a4)超出该结构体大小(360),因此不匹配。 ### 自动计算工具方法 在内核模块中编写测试代码: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/stddef.h> struct suspect_struct { // 填充成员直到覆盖420字节 }; static int __init debug_init(void) { printk(KERN_INFO "suspect_struct.error_code offset: %ld\n", offsetof(struct suspect_struct, error_code)); // 如果不是这个成员名,需要调整 return 0; } static void __exit debug_exit(void) { } module_init(debug_init); module_exit(debug_exit); MODULE_LICENSE("GPL"); ``` ### 结论:如何判断 1. **通过反汇编定位代码**:确定访问指令所在函数,分析函数操作的结构体类型 2. **检查内核头文件**:搜索包含至少420字节的结构体 3. **计算偏移**:对候选结构体使用`offsetof`计算成员偏移 4. **运行时验证**:在内核模块中动态打印偏移值 ### 关于int型的大小 - 在Linux内核中,`int`类型始终是32位(4字节),无论用户空间如何。内核使用固定大小的类型(如`u32`, `s64`)来确保可移植性。 §§相关问题§§: 1. 如何在Linux内核中动态获取结构体成员偏移? 2. 内核数据类型的大小在不同体系结构(如ARM、x86)下有何差异? 3. 如何通过Oops日志反汇编定位触发空指针解引用的具体代码行? 4. 编写内核模块时有哪些常用工具可以预防结构体偏移计算错误? </think> ### 判断 `1a4` 属于哪个结构体以及 `int` 的大小 这个虚拟地址 `0x1a4` (420 字节) 是一个结构体的成员偏移量。要确定它属于哪个结构体,需要通过系统调试信息和内核源码分析。以下是完整解决方案: #### 1. **确定 `int` 类型的大小** 在 Linux 内核中: - `int` 类型始终是 **4 字节** (32 位) - 不受架构影响(x86/x86_64/ARM 均为 4 字节) - 内核使用固定大小的类型确保可移植性 ```c // 验证代码:打印内核中int的大小 #include <linux/module.h> #include <linux/kernel.h> static int __init size_init(void) { printk(KERN_INFO "Size of int: %zu bytes\n", sizeof(int)); printk(KERN_INFO "Size of long: %zu bytes\n", sizeof(long)); printk(KERN_INFO "Size of pointer: %zu bytes\n", sizeof(void*)); return 0; } static void __exit size_exit(void) {} module_init(size_init); module_exit(size_exit); MODULE_LICENSE("GPL"); ``` **输出示例** (64位系统): ``` Size of int: 4 bytes Size of long: 8 bytes Size of pointer: 8 bytes ``` #### 2. **定位结构体的方法** ##### 方法 1:使用 `pahole` 工具分析内核结构体 ```bash # 1. 获取内核调试符号 sudo apt install linux-image-$(uname -r)-dbgsym # 2. 使用pahole分析特定结构体 pahole -C task_struct /usr/lib/debug/boot/vmlinux-$(uname -r) | grep -B 10 -A 10 '420' ``` ##### 方法 2:在内核模块中动态打印偏移量 ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/stddef.h> // 包含offsetof宏 struct suspect_struct { char buffer[400]; int status; int config; int error_code; // 目标成员 }; static int __init offset_init(void) { printk(KERN_INFO "error_code offset: %lu\n", offsetof(struct suspect_struct, error_code)); return 0; } static void __exit offset_exit(void) {} module_init(offset_init); module_exit(offset_exit); MODULE_LICENSE("GPL"); ``` #### 3. **完整推导过程** 已知条件: - 访问地址 = 基地址 + 偏移量 `0x1a4` (420) - `int` 大小 = 4 字节 - 典型结构体布局示例: ```c struct device_driver { char name[64]; // 0-63 (64字节) struct module *owner; // 64-71 (8字节指针) int version; // 72-75 (4字节) int flags; // 76-79 (4字节) char buffer[256]; // 80-335 (256字节) long settings[8]; // 336-399 (8×8=64字节) int error_reg; // 400-403 (偏移量0x190) int status_reg; // 404-407 (偏移量0x194) int control_reg; // 408-411 (偏移量0x198) int reserved[2]; // 412-419 int error_code; // 420-423 (偏移量0x1a4) }; ``` 推导步骤: 1. 420 ÷ 4 = 105 → 排除纯整型数组(105个int太少见) 2. 检查包含混合类型的常见内核结构体: ```bash grep -rn 'struct' /usr/src/linux-headers-$(uname -r)/include | grep '420' ``` 3. 结合Oops日志中的函数名(如 `dev_read`) 4. 确认最终结构体: ```c struct custom_device { // ... 其他成员 ... int error_code; // 偏移420 }; ``` #### 4. **自动化调试脚本** ```bash #!/bin/bash # 查找包含420偏移的结构体成员 KERN_VER=$(uname -r) DEBUG_SYM="/usr/lib/debug/boot/vmlinux-$KERN_VER" for struct in $(pahole -l $DEBUG_SYM); do pahole -C $struct $DEBUG_SYM | awk -v offset=420 ' /^{/ { start=1; } start && /^[ \t]*[^ \t;]+ [^ \t]+;/ { if ($NF == ";") sub(/;/, ""); member=$NF; getline; if ($1 == "/*" && $2 == "offset") { off_str=$3; gsub(/[^0-9]/, "", off_str); if (off_str == offset) { print "结构体:", struct, "成员:", member; } } } /^}/ { start=0; } ' struct="$struct" done ``` ### 关键结论 1. **`int` 大小**:Linux内核中固定为 **4字节** 2. **偏移量 `0x1a4`**: - 对应十进制 420 字节 - 很可能是某个设备驱动结构体中的 `error_code` 成员 - 需要结合Oops日志中的上下文函数名确认具体结构体 3. **典型模式**: - 前400字节:配置/缓存区 - 后续20字节:状态寄存器组 - 420偏移处:错误代码寄存器
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值