我知道我的问题可能是非常基本的,但是我想知道在内存中有多个单元格的对象,比如数组和用户定义的对象(在内存中需要多个单元格,因此具有连续地址的范围)记忆),指针对这类物体的意义何在?是C中的变量包含内存中这些对象的地址(逻辑上不正确,因为这些对象在内存中占用了多个单元格,因此具有连续地址的范围),或者说,指向这些对象的指针只是开始这些对象的地址(更合理) .
请帮我理解;如果你不相信我对C指针定义的解释,请给我一个正确的解释 .
在大多数C教程中,它说指针只包含内存中其他变量的地址 .
如果我(作为编译器)知道 int (在这个特定系统上)是4个字节长,指向 int 的指针只需要告诉我 int 的"start"在哪里:我只需要读取它和接下来的3个字节!
int
对于像数组这样的大型数据结构,同样如此:如果我知道我的数组在哪里开始,我知道我可以通过将一个项的大小添加到地址来访问每个后续元素 . 例如,如果我从地址100开始 int a[] , int 是4个字节,那么
int a[]
a[32] = (address of a) + (32 * size of int) = 100 + 128 = 228 所以字节228到231是a [32]处的整数 .
a[32] = (address of a) + (32 * size of int) = 100 + 128 = 228
使这稍微容易使用的是编译器为我们抽象出不同大小的数据类型 . 如果我将1添加到整数指针,地址实际上会增加4!这是因为我很少(几乎从不)想要读取半个整数:我更有可能依次查看一系列整数 .
假设你有一个变量 a 声明并初始化为
a
int a = 5;
然后创建一个指针并使用address-of运算符 & 使int指向 a :
&
int* pointer_to_a = &a;
pointer_to_a 的实际值是 a 在内存中的地址 . 但编译器知道它是一个指针,因此您可以使用 pointer_to_a 访问 a 的内容,并使用解除引用运算符 * :
pointer_to_a
*
*pointer_to_a = 10; std::cout << "a = " << a << '\n';
当您设置 pointer_to_a 指向 10 的位置时,上面将打印 10 .
10
从here
计算机的内存可以想象成一系列内存单元,每个内存单元都是计算机管理的最小尺寸(一个字节) . 这些单字节存储器单元以连续方式编号,因此,在任何存储器块内,每个单元具有与前一个单元相同的编号 . 这样,每个单元可以容易地位于存储器中,因为它具有唯一的地址并且所有存储器单元遵循连续的模式 . 例如,如果我们正在寻找细胞1776,我们知道它将在1775和1777细胞之间,正好在776之后的一千个细胞和细胞2776之前的正好一千个细胞 . ] 1
这可能有助于想象OS的内存布局Here
当你指定一个指针时,你还要指定它将保持的类型指针,例如int *在这种情况下,编译器将保留4个字节(通常为int的大小)并以little-endian / big-endian格式存储该值 .
我认为你是正确的,它只有一个指向起始单元格的指针,如果你说p,那么编译器将增加4个字节并指向其他地址 .
如果你想引用p指向的下一个单元格,那么认为你可能需要读取地址(HEX地址)并增加和推荐它 .
对于数组,指针与其他所有内容完全相同 .
一个指针指向一个对象的位置(回复unwind的指针到数组的对象:这个对象也可能是一个数组),不多也不少 . 如果有一个对象(并且不关心),它不知道对象数组的大小.1完全可以创建一个指向单个值的指针,并将其作为一个大小的数组访问,尽管这既不明确也不明智(它可能会崩溃) . 完全可以使用指向大小为5的数组的指针并访问第10个元素 . 同样,这没有意义,可能会崩溃,但没有什么能阻止你这样做(除了编译时常量索引,至少有一些编译器)可能警告) . 指针不知道 .
对于一个结构,指针知道结构在内存中的位置,不多也不少 . 最重要的是,编译器知道其他详细信息,例如成员到此基址的偏移量 . 但是,此信息绑定到用于取消引用指针的类型(而不是指针本身!) .因此,通常可以通过 Banana 指针访问 Car 对象,如果您将 Banana 指向汽车(通过演员,意外或算术) . 当然,这不可能 . 指针不知道差异,编译器将执行"as if" .
Banana
Car
1是的,如果它是一个指向数组的指针,编译器就知道该数组的大小 . 但这只对类型的正确性有影响 . 你'll get a compile error trying to assign an array-of-5 to a pointer-to-array-of-4, because they'有不同的东西 . 但这与指针无关 . 指针仍然不知道数组的大小,它仍然不知道是否有一个数组或一个数组的数组 . 您仍然可以使用它(可能是灾难性的效果),并且没有任何逻辑可以阻止您造成伤害 .
5 回答
如果我(作为编译器)知道
int
(在这个特定系统上)是4个字节长,指向int
的指针只需要告诉我int
的"start"在哪里:我只需要读取它和接下来的3个字节!对于像数组这样的大型数据结构,同样如此:如果我知道我的数组在哪里开始,我知道我可以通过将一个项的大小添加到地址来访问每个后续元素 . 例如,如果我从地址100开始
int a[]
,int
是4个字节,那么a[32] = (address of a) + (32 * size of int) = 100 + 128 = 228
所以字节228到231是a [32]处的整数 .使这稍微容易使用的是编译器为我们抽象出不同大小的数据类型 . 如果我将1添加到整数指针,地址实际上会增加4!这是因为我很少(几乎从不)想要读取半个整数:我更有可能依次查看一系列整数 .
假设你有一个变量
a
声明并初始化为然后创建一个指针并使用address-of运算符
&
使int指向a
:pointer_to_a
的实际值是a
在内存中的地址 . 但编译器知道它是一个指针,因此您可以使用pointer_to_a
访问a
的内容,并使用解除引用运算符*
:当您设置
pointer_to_a
指向10
的位置时,上面将打印10
.从here
这可能有助于想象OS的内存布局Here
当你指定一个指针时,你还要指定它将保持的类型指针,例如int *在这种情况下,编译器将保留4个字节(通常为int的大小)并以little-endian / big-endian格式存储该值 .
我认为你是正确的,它只有一个指向起始单元格的指针,如果你说p,那么编译器将增加4个字节并指向其他地址 .
如果你想引用p指向的下一个单元格,那么认为你可能需要读取地址(HEX地址)并增加和推荐它 .
对于数组,指针与其他所有内容完全相同 .
一个指针指向一个对象的位置(回复unwind的指针到数组的对象:这个对象也可能是一个数组),不多也不少 . 如果有一个对象(并且不关心),它不知道对象数组的大小.1
完全可以创建一个指向单个值的指针,并将其作为一个大小的数组访问,尽管这既不明确也不明智(它可能会崩溃) . 完全可以使用指向大小为5的数组的指针并访问第10个元素 . 同样,这没有意义,可能会崩溃,但没有什么能阻止你这样做(除了编译时常量索引,至少有一些编译器)可能警告) . 指针不知道 .
对于一个结构,指针知道结构在内存中的位置,不多也不少 . 最重要的是,编译器知道其他详细信息,例如成员到此基址的偏移量 . 但是,此信息绑定到用于取消引用指针的类型(而不是指针本身!) .
因此,通常可以通过
Banana
指针访问Car
对象,如果您将Banana
指向汽车(通过演员,意外或算术) . 当然,这不可能 . 指针不知道差异,编译器将执行"as if" .1是的,如果它是一个指向数组的指针,编译器就知道该数组的大小 . 但这只对类型的正确性有影响 . 你'll get a compile error trying to assign an array-of-5 to a pointer-to-array-of-4, because they'有不同的东西 . 但这与指针无关 . 指针仍然不知道数组的大小,它仍然不知道是否有一个数组或一个数组的数组 . 您仍然可以使用它(可能是灾难性的效果),并且没有任何逻辑可以阻止您造成伤害 .