当你可以使用指针时,使用malloc有什么意义?

你不能只使用指针存储尽可能多的数据吗? 为什么必须使用malloc()来获得更多内存?

 int * a; int max, i; printf("Enter the maximum number you want: "); scanf("%d", &max); for (i = 0; i < max; i++) { * (a + i) = i; } for (i = 0; i < max; i++) { printf("%d\n", * (a + i)); } return 0; 

所以我让用户选择任何数字,电脑会“分配内存”吗? 而不是使用以下代码:

 a = (int *) malloc(10 * sizeof(int)); 

在你的代码中,

  * (a + i) = i; 

是错的,因为你试图写入未初始化的内存。 这反过来调用未定义的行为 。

详细说明,仅定义指针不会自动为该指针分配无限可访问内存。 您需要添加指针指向的位置。 当您只是定义一个指针(本地)时,它指向一个未知的内存位置,这很可能既不是有效的,也不是程序可以访问的。 因此,当您尝试访问该内存位置时,它实际上是访问一些无效内存。 这是UB。

所以,

为什么你必须使用malloc来获得更多内存?

malloc()不用于获取更多内存,而是提供要访问的所需内存位置。


编辑:

关于你的编辑,

  a = (int *) malloc(10 * sizeof(int)); 

要添加两件事,

  1. 请参阅为什么不在 Cmalloc()和family的返回值。
  2. 在使用返回的指针之前,请务必检查malloc()是否成功。

指针必须指向内存中的某个位置,所以永远不要写

 int* x; *x=...; 

但写

 int* x=expression that results in an valid address; 

首先考虑一台没有MMU的简单计算机和一个花哨的多任务操作系统。 然后您可以使用任何地址,但您必须知道您不会替换您的代码和任何重要数据。 您将受益于为代码,调用堆栈和其他数据提供保留空间。 有些机器将地址连接到外围设备,因此在那里写一些物理内容会发生。 这称为内存映射I / O. 要知道你在做什么,你可以创建你的地址布局,这在16位机器上可能看起来像

 +------------------+ 0x0000 | Memory mapped IO | +------------------+ 0x0100 | Program | | | +------------------+ 0x4000 | Call stack | | (local variables)| +------------------+ 0x8000 | Other data | | globals | | heap | +------------------+ 0xffff 

这个虚构的机器有255个I / O端口(保留0x0000),并将在地址0x0100上启动程序。 地址布局的其余部分由您决定。 这里为程序保留了16128个字节,堆栈为16384个字节,其他数据为32767个字节。 如果您知道您的程序永远不会超过8 kB,那么随意增加您的调用堆栈或堆。 设定电机转速的程序可能看起来像

 int main() { const uint8_t* speed_regulator=(const uint8_t*)0x0001; //Port for speed controller is 0x0000 uint8_t* motor_voltage=(uint8_t*)0x0002; //Port for motor controller while(true) { *motor_voltage=*speed_regulator; } } 

这里必须要小心,因此编译器不会优化循环,这是我们的数据泵。

现在你想要一个带有虚拟内存和所有现代东西的多任务系统。 但是你不能再使用任意地址了。 为了能够为您提供有效的地址,并告知操作系统您需要多少内存,函数malloc存在。

所以我让用户选择任何数字,电脑会“分配内存”吗?

有些语言就是这样的; 运行时环境将根据需要从堆(或任何内存池)中分配内存。

C不起作用。 当你申报时

 int *a; 

a最初并未指出任何有意义的内容; 如果声明为static或在文件范围内,它最初包含NULL ,如果在块中声明它包含一个不确定的值,该值可能会也可能不会指向可写的内存位置。 它不会自动指向堆,并且写*(a + i) = i (或a[i] = i ,这是相同的事情)将不会自动分配任何新内存。

C给程序员带来了管理动态分配内存的所有负担。 如果在运行时需要额外的内存,则必须使用mallocrealloc ,当您完成该内存后,必须使用free释放它。