C

时间:2018-05-20 13:02:13

标签: c arrays pointers stack

#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]);

程序崩溃了。

为什么会有区别?

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];
  • int *表示变量n是指向内存地址的指针
  • &amp; nums [3]在内存中给出数组nums中第三个元素的地址

所以在那行代码之后,在变量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]

中的值