这是一个概念性的问题,让我更好地理解C.根据我对C数组的理解,它们存储指向按照分配的空间顺序生成的值的指针。例如,如果我有这个代码
char someCharArray[] = {'a', 'b', 'c'};
假设我的堆没有为此数组提供连续的12位,因此我将指针存储到以下非连续地址0x001, 0x011, 0x040
。
我知道有两种方法可以访问此数组中的值,如this answer所示。
让我说我像这样访问数组的第二个元素
char datPointer = someCharArray[1];
在这种情况下,datPointer
将指向0x011
,因为地址存储在数组中。
但是,以下代码是否会返回错误的地址?
char datWrongPointer = (someCharArray + 1);
因为我将顺序地址添加到someCharArray的起始地址,所以假设字符为4位,我将datWrongPointer
变为0x004
而不是它应该是什么?也许我误解了添加功能,但如果有人能向我解释,我会很感激。
答案 0 :(得分:4)
根据我对C数组的理解,它们存储指向值的指针
不,数组直接存储值。实际上,基本上的数组是它们的元素。 C不增加额外的结构。
char someCharArray[] = {'a', 'b', 'c'};
好的,这里someCharArray
由3个字节的内存组成。如果它存在于静态存储中(例如因为它是全局变量),则该存储器通常是数据部分的一部分;如果它存在于自动存储器中(即它是一个局部变量),它通常放在堆栈上。
让我们说我的堆没有这个数组的顺序12位
这里的堆是如何涉及的?为什么12位? C并不真正支持小于1字节的对象(字节不能小于8位)。
为了一个例子,我们假设someCharArray
最终被放置在地址0xAB0000处。然后第一个元素位于0xAB0000,第二个元素位于0xAB0001,第三个元素位于0xAB0002。
char datPointer = someCharArray[1];
datPointer
不是指针,它只是一个char
。此代码会将'b'
分配给datPointer
(因为someCharArray[1]
为'b'
)。
char datWrongPointer = (someCharArray + 1);
这是类型错误。
someCharArray
计算指向其第一个元素的指针(如数组所做的那样,除非它们是sizeof
或&
的操作数)。这为我们提供了char *
类型的值(并且在上面,值为0xAB0000)。
我们添加1,它添加了足够的字节来到达内存中的下一个元素。这里的指针类型为char *
,因此我们将1 * sizeof (char)
(只是1 * 1
,只是1
)添加到原始指针值。
我们最终得到一个char *
,其值为0xAB0001。
然后我们尝试分配一个指向普通char
的指针,该指针无效。但是我们可以用*
取消引用指针并获取存储在那里的值:
char x = *(someCharArray + 1); // 'b'
...或者我们可以使用指针变量:
char *ptr = someCharArray + 1; // 0xAB0001 in this example