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

C语言动态内存疑问:越界访问无报错、sizeof未显示实际大小

问题描述

代码示例

int main(){
  printf("%lu\n",(1 * sizeof(int)));
  int* hello=malloc(1 * sizeof(int));
  hello[1000000]=10;
  printf("%d\n",hello[1000000]);
  printf("%lu\n", sizeof(hello));

  int* goodbye=malloc(100 * sizeof(int));
  printf("%lu\n",sizeof(goodbye));

  hello=goodbye;

  printf("%lu\n",sizeof(hello));

  hello=realloc(hello,20);

  hello[1]=0;

  printf("%lu\n",sizeof(hello));
}

程序输出

4
10
8
8
8
8

困惑点

  1. 只为hello分配了4字节内存,却能访问hello[1000000]且无任何警告或错误;
  2. 尝试通过将hello赋值为goodbye、调用realloc调整大小,但sizeof始终返回8,无法反映数组实际大小;
  3. 想要实现动态大小的int数组,不知道哪里出错了。

问题解答

1. 越界访问为何没报错?

C语言本身不做数组边界检查,这是出于性能优先的设计。你访问hello[1000000]属于未定义行为——这次碰巧能读写成功,只是因为那块内存暂时没被程序或系统占用/保护,并不是合法操作。如果那块内存被其他数据占用,你的写入会破坏原有数据,导致程序崩溃、数据错乱等不可预测的后果。

编译器默认不会主动检测这种越界,但可以开启编译警告(比如GCC的-Wall -Wextra),部分情况下能发现明显的越界问题,但无法覆盖所有场景。

2. 为什么sizeof(hello)始终返回8?

hello是指针变量,不是数组。在64位系统中,指针的大小固定为8字节(32位系统是4字节),sizeof计算的是指针本身的大小,而非它指向的内存块的大小。

C语言不会自动跟踪动态分配内存的大小,malloc/realloc也不会把这个信息存在指针里,你需要手动用单独变量记录动态数组的实际大小。

3. 如何实现动态大小的int数组?

要实现动态数组,需要同时维护指针和当前数组的大小/容量:

示例代码:

#include <stdio.h>
#include <stdlib.h>

int main(){
    // 动态数组的指针、当前元素个数、容量(用于扩容优化)
    int* arr = NULL;
    size_t count = 0;
    size_t capacity = 0;

    // 初始分配,容量设为4个int
    capacity = 4;
    arr = malloc(capacity * sizeof(int));
    if(arr == NULL){
        perror("malloc failed");
        return 1;
    }

    // 添加元素,元素个数达到容量时扩容
    for(int i=0; i<10; i++){
        if(count >= capacity){
            // 扩容为原来的2倍
            capacity *= 2;
            int* temp = realloc(arr, capacity * sizeof(int));
            if(temp == NULL){
                perror("realloc failed");
                free(arr);
                return 1;
            }
            arr = temp;
        }
        arr[count] = i;
        count++;
    }

    // 输出数组信息
    printf("数组元素:");
    for(size_t i=0; i<count; i++){
        printf("%d ", arr[i]);
    }
    printf("\n当前元素个数:%zu,当前容量:%zu\n", count, capacity);

    // 释放内存,避免泄漏
    free(arr);
    arr = NULL;
    return 0;
}

核心要点:

  • 用单独变量记录数组的实际元素个数和容量(容量是已分配内存能容纳的最大元素数,个数是当前已使用的元素数);
  • 每次添加元素前检查是否需要扩容,用realloc重新分配内存时,必须检查返回值(失败会返回NULL,此时原有内存不会被释放);
  • 不再使用动态数组时,一定要用free释放内存,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 07:18:19