问题描述
我的思绪现在很混乱,很受打击,希望有人能帮我解惑/让我重新走上正确的道路。
如果我错了,请纠正我,但在 C 中,您使用 malloc 来“保留”/获得一定数量的内存空间(以字节为单位)。
所以 int* ptr = malloc(10 * sizeof(int));
会分配 40 字节的内存/将指向内存中该区域的指针分配给变量/指针 ptr(假设在这台机器上 int 是 4大字节).
我不明白的是,当您为数组分配值时,为什么 i 是 i++(1 增量)而不是 i + 4 又名 int 的大小。这是有道理的,因为我们有一个 40 字节的内存块,我们迭代了 10 次 à +4 字节 => 40 字节。
代码示例: 假设,为了简单起见,函数 random() 返回一个随机整数。
for(int i = 0; i < 10; i++) {
*(ptr + i) = random();
}
(我对 i+4 Bytes 的想法,产生了奇怪的结果,错误的方式):
for(int i = 0; i < 10; i+=4) {
*(ptr + i) = random();
}
我的问题是,当 int 有 4 个字节大时,为什么 ptr + i (i+1) 选择每个 int 的正确地址,我们甚至保留了 40 个字节的内存,而不是 10 个字节。也就是为什么 ptr + i (i+4) 错了吗?
(对我的大脑来说,迭代 i+4 而不是 1 是有意义的。通过 malloc 分配的 start/ptr => 0x400,一个 int 是 4 个字节大所以下一个地址/下一个 int 在 0x404、0x408 等处。 .. 不是 0x401,0x402 ....)
解决方法
指针运算和内存分配是两件不同的事情。
指针运算总是基于被指向对象的类型来完成。也就是说,指针算术总是包含一个自动的、隐式的乘以那个大小。所以
int *p;
/* ... */
p++;
总是将 p
中的地址增加 sizeof(int)
字节。
必须如此,因为除其他外,指针算术模拟数组访问。所以它必须考虑指向对象的大小,以便像
这样的符号*(p + 1)
和
p[1]
正常工作。
另一方面,malloc
函数总是以字节为单位进行处理。一个原因——也许是原因——正是 malloc
是一个函数。当你说这样的话
malloc(10 * sizeof(int))
您机器上的 malloc
函数接收到的数字仅为 40。malloc
无法知道这是 40 个大小为 1 的东西,还是 10 个大小为 4 的东西,还是一个大小为 40。它只知道它必须分配 40 个字节。 (也有关于对齐的要求。)
如果你希望它以不同的方式工作——如果你想要类似的东西
int *ip = malloc(10);
自动缩放 sizeof(int)
-- 很难看出它在 C 中是如何工作的。(相比之下,在 C++ 中有 new[]
,它可以并且确实将分配对象的大小放入帐户。)
如果 p
是指向 T
类型对象的指针,则 p+1
产生指向类型的下一个对象的地址; p++
前进 p
以指向下一个对象。
给定
char *cp = (char *) 0x1000;
short *sp = (short *) 0x1000; // assume 2-byte short
long *lp = (long *) 0x1000; // assume 4-byte long
那么以下是正确的:
char short long
+–––+ +–––+ +–––+
0x1000 | | <––cp | | <––sp | | <-–lp
+–––+ + - + + - +
0x1001 | | <-–cp+1 | | | |
+———+ +———+ + - +
0x1002 | | <––cp+2 | | <––sp+1 | |
+———+ + - + + - +
0x1003 | | <––cp+3 | | | |
+–––+ +–––+ +–––+
0x1004 | | <––cp+4 | | <––sp+2 | | <––lp+1
+———+ + - + + - +
... ... ...