#line 1----int nums[7] = {5,6,7,8,9,10,11};
#line 2----int *n = &nums[3];
#line 3----printf("n[0]=%d n[1]=%d n[2]=%d \n", n[0], n[1], n[2]);
输出:
n [0] = 8 n [1] = 9 n [2] = 10
第一个问题:
Array是C中的LinkedList,这就是为什么第3行中打印的第3行中的值还包括nums [4],nums [5]等等的值(等等) 8,9,10 ...等)?
第二个问题:
为什么会出现"&"在2号线签到?如果我创建一个变量并将其打印出来,而不使用&标志,它打印正常,例如:
int *x = 50;
printf("X: %d",x) // prints out 50
但如果我这样做:
int *x = 50;
printf("X: %d", &x) // prints out 684958....some long number
然而,当它是一个数组时,在上面的例子中:
#line 2----int *n = nums[3]; // I removed the & from &nums[3]
#line 3----printf("n[0]=%d n[1]=%d n[2]=%d \n", n[0], n[1], n[2]);
程序崩溃了。
为什么会有区别?
答案 0 :(得分:3)
第一个问题: 数组是C中的链接列表吗?不,数组和链接列表都不同。 LinkedList
(类似/不同的2种数据类型的集合)可以array
(类似数据类型的集合)作为其一部分,但两者不相同。
int nums[7] = {5,6,7,8,9,10,11};
此处nums
是一个包含7个整数的数组,所有元素都存储在连续内存位置&数组名称表示其基址。假设nums
起始地址为0x100
,那么它看起来像
nums[0] nums[1] nums[2] nums[3] nums[4] nums[5] nums[6]
-------------------------------------------------------------------------
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
-------------------------------------------------------------------------
0x100 0x104 0x108 0x112 0x116 0x120 0x124
nums
LSB
接下来当语句int *n = &nums[3];
执行时,n
是整数指针,并指向&nums[3]
,如0x112
,如上所示。因此,对于n
n[0]
,0x112
不是0x100
,如果增加n
,则增加4个字节&等等。
-----------
| 0x112 | <--- int *n = &nums[3]; /* n is pointer and it needs address and here & is unary operator and &num[3] is assigned to n */
----------
n
并且
---------------------------------------------------------------------
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---------------------------------------------------------------------
0x100 0x104 0x108 0x112 0x116 0x120 0x124
| | | |
n[0] n[1] n[2] n[3]
从你的问题,代码块
int *n = nums[3]; // I removed the & from &nums[3]
printf("n[0]=%d n[1]=%d n[2]=%d \n", n[0], n[1], n[2]);
此处n
指向8
并且它不是有效地址,看起来像
---------
| 8 | <-- not that n is int pointer
---------
n
当您尝试打印n[0]
时,由于您尝试打印地址为8
的无效地址,因此会崩溃,地址8
可能会保留用于其他目的,不适用于您的可执行文件a.out
。
n[0] = *(n + 0)
= *(8) = you are dereferencing invalid address which causes crash
另外
int *x = 50;
printf("X: %d",x) // it prints what X holds and that is 50
printf("X: %d", &x); /* &X means address of X, its an address not some long number , also use %p format specifier to print address. */
printf("X: %d", *x); /* this will cause crashes, as X points to invalid address
这里x
是一个整数指针&amp;它应该用有效的地址初始化,如
int var = 50;
int *x = &var; /* now x points to valid address */
printf(" value at the address : %d\n",*x);/* prints 50 */
最后我的建议是阅读一本好的C
书&amp;了解阵列&amp;指针章节非常好。
答案 1 :(得分:1)
回答你的第一个问题。
数组与链表不同。数组的元素存储在一行的内存中,而链表的元素则分散在内存中。这意味着如果您知道数组中第一个元素的地址,那么您可以通过向第一个元素的地址添加1来访问数组的第二个元素,因为它们是一个接一个地存储的。您不能使用列表执行此操作,因为列表的元素遍布内存,并且在列表的一个元素中,您必须具有指向存储第二个元素的另一个内存位置的指针。
现在这行代码
int *n = &nums[3];
所以在那行代码之后,在变量n中,你有一个数组nums的第三个元素的内存位置。因为元素在编程语言c中一个接一个地存储,所以可以通过向n的值加1来访问nums的第四个元素。这就是你的printf功能
的原因printf("n[0]=%d n[1]=%d n[2]=%d \n", n[0], n[1], n[2]);
正在打印9 10和11.
&amp; nums ==&amp; nums [0]&lt; ==&gt;元素5的内存地址
&amp; nums [3]&lt; ==&gt;内存地址是元素9的内存地址,因为它在5之后是3个位置
第二个答案
标志“&amp;”第2行给出了存储元素nums [3]的存储位置。
在这行代码中
int *x = 50;
你是说x指向内存地址50.这就是为什么你得到50这样的printf函数
printf("%d\n",x);
但是当有符号“&amp;”时前缀为x,然后打印存储在内存地址50
上的值printf("%d\n",&x);
这就是为什么输出是一些数字60435 ......
你问的最后一件事是为什么你的程序在这两行之后崩溃,当你删除前缀&amp;变量nums [3]
int *n = nums[3]
printf("n[0]=%d n[1]=%d n[2]=%d \n", n[0], n[1], n[2]);
这是因为现在变量n指向内存地址8 == nums [3],你可能无法访问那个内存,这就是它崩溃的原因。
记住int * n =&amp; nums [3]指向nums [3]的内存地址,但是当你输入int * n = nums [3]时它比poit到内存地址8因为8是存储在nums [3]
中的值