【问题标题】:Basic Behaviour of Arrays and Pointers in C [closed]C中数组和指针的基本行为[关闭]
【发布时间】:2018-10-30 07:11:29
【问题描述】:
#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

第一个问题:

数组是 C 中的 LinkedList,这就是为什么第 2 行中的值(在第 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]);

程序崩溃。

为什么这里有区别?

【问题讨论】:

  • 数组是 C 中的 LinkedList 不,它不是。这是一个线性的记忆序列。
  • 您是否查找过一元运算符& 的实际作用?您不能在程序中添加和删除随机字符并期望它正常运行。在 C 语言中,这可能会导致您得出错误的结论,因为有太多未定义的行为。您必须阅读一本书并遵循教程,C 是一门小语言,但您必须学习技术和文化。

标签: c arrays pointers stack


【解决方案1】:

第一个问题: 数组在 C 中是 LinkedList 吗? 不,数组和linkedList 是不同的。 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 可能被保留用于其他目的,而不是为您的可执行文件@987654346 @。

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 是一个整数指针,它应该使用有效地址进行初始化,例如

int var = 50;
int *x = &var; /* now x points to valid address */
printf(" value at the address : %d\n",*x);/* prints 50 */

最后我的建议是阅读一本好的 C 书籍并很好地理解数组和指针章节。

【讨论】:

  • 赞成:您可以给新手的最佳答案。很高兴指出一本书会有所帮助。这样的基础知识是每个 C 教程的一部分,对于 Stackoverflow 来说并不是真正的问题。
【解决方案2】:

回答你的第一个问题。

数组不像链表。数组的元素在内存中连续存储,而链表的元素分散在内存中。这意味着如果您知道数组中第一个元素的地址,那么您可以通过将第一个元素的地址加 1 来访问数组的第二个元素,因为它们是一个接一个地存储的。您不能对列表执行此操作,因为列表的元素遍布整个内存,并且在列表的一个元素中,您必须有一个指向存储第二个元素的另一个内存位置的指针。

现在这行代码

 int *n = &nums[3];
  • int * 表示变量n是指向内存地址的指针
  • &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。

&nums == &nums[0] 元素5的内存地址

&nums[3] 元素9的内存地址,因为它在5之后3位

第二个答案

第 2 行中的符号“&”为您提供存储元素 nums[3] 的内存位置。

在这行代码中

int *x = 50;

你是说 x 指向内存地址 50。这就是为什么你得到 50 作为这样的 printf 函数的结果

printf("%d\n",x);

但是当 x 有符号“&”前缀时,那么你正在打印存储在内存地址 50 上的值

printf("%d\n",&x);

这就是为什么输出是某个数字 60435...

您问的最后一件事是,当您删除变量 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= &nums[3] 指向的是 nums[3] 的内存地址,但是当你只输入 int *n=nums[3] 时,它指向的是内存地址 8,因为 8 是值存储在 nums[3]

【讨论】:

  • 地址不加一。这是错误的。给数组元素类型的指针加一。
猜你喜欢
  • 2018-08-26
  • 2016-04-24
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多