You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言数组与sizeof()技术疑问:内存、实现及源码查询

C数组与sizeof相关问题解答

问题背景与代码示例

#include <stdio.h>

char array1[3] = { 0,0,0 };
char array2[4] = { 0,0,0,0 };

char* a1 = array1;
char* a2 = array2;

int main(void) {
    printf("Array 1 Memory: %p\n", a1);
    printf("Array 2 Memory: %p\n\n", a2);

    //Array 1 set values and display addresses.
    printf("array1 = [");
    for (int i = 0; i < 5; i++) {
        array1[i] = i;
        printf("%d, ", array1[i]);
    }
    printf("\n");

    for (int i = 0; i < 4; i++) {
        printf("array1[%d] memory location: %p\n",i, a1 + i);
    }
    printf("size of array1 = %d\n", sizeof(array1));
    printf("]\n"); 

    //Array 2 display values and addresses
    printf("array2 = [");
    for (int i = 0; i < 4; i++) {
        printf("%d, ", array2[i]);
    }
    printf("\n");
    for (int i = 0; i < 4; i++) {
        printf("array2[%d] memory location: %p\n", i, a2 + i);
    }
    printf("size of array2 = %d\n", sizeof(array2));
    printf("]\n");

    printf("array2[-1] = %d\n", array2[-1]);

    return 0;
}

运行输出

Array 1 Memory: 005CA4F4
Array 2 Memory: 005CA4F8

array1 = [0, 1, 2, 3, 4,
array1[0] memory location: 005CA4F4
array1[1] memory location: 005CA4F5
array1[2] memory location: 005CA4F6
array1[3] memory location: 005CA4F7
size of array1 = 3
]
array2 = [4, 0, 0, 0,
array2[0] memory location: 005CA4F8
array2[1] memory location: 005CA4F9
array2[2] memory location: 005CA4FA
array2[3] memory location: 005CA4FB
size of array2 = 4
]
array2[-1] = 3

疑问解答

1. 越界赋值后sizeof(array1)仍返回3的原因

sizeof是编译期运算符,它的值完全由数组的声明类型决定,和运行时的内存操作无关。当你声明char array1[3]时,编译器在编译阶段就已经确定了这个数组的大小是3字节,后续运行时哪怕你越界写入了额外的内存,也不会改变编译器对数组类型的认知——数组的大小信息是编译时的类型元数据,不会存储在运行时的内存中。另外,数组越界写入属于C语言中的未定义行为,可能会破坏其他变量的内存,绝对不要这么做。

2. sizeof的定义与实现逻辑

sizeof不是普通函数,而是C语言标准规定的运算符,所以不会在stdio.h或其他头文件里有函数声明。它的行为由C标准(如C11、C17)明确:

  • 对于基本数据类型(如int、char),返回该类型的字节数;
  • 对于数组类型,返回数组总字节数(元素个数 × 单个元素字节数);
  • 对于指针类型,返回当前平台下指针的字节数(比如32位系统是4,64位是8)。

编译器在编译阶段就会计算sizeof表达式的值:对于静态数组、常量类型,直接替换为对应的常量数值;对于动态类型(如变长数组),则会生成运行时计算的代码。想了解具体实现,可以看GCC、Clang等开源编译器的源码,它们在前端语法分析阶段就会处理sizeof表达式。

3. C编译器源码与数组创建机制

常见的开源C编译器有GCC、Clang/LLVM,你可以直接获取它们的源码来研究。以char array[3]为例:

  • 如果是全局数组,编译器会在程序的数据段预留3个char大小的连续内存空间;如果是函数内的局部数组,则会在栈上分配空间。
  • 数组的大小是编译期确定的类型信息,不会存储在运行时内存中。编译器只会在编译阶段用这个大小做静态检查(比如开启-Wall警告时,越界访问会被提示),但运行时没有任何机制维护数组的大小,所以越界访问不会被自动拦截。

内容的提问来源于stack exchange,提问作者ryanc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:01:55