本文介绍了不一致使用指针,直接一个数组的数组和地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这code样品正确打印阵列。

This code sample prints the array correctly.

int b[2] = {1, 2};
int *c = &b;
int  i, j,k = 0;
for (i = 0;i < 2; i++) {
    printf("%d ", *(c+i));
}

而这一次打印两垃圾值。

while this one prints two garbage values.

int b[2] = {1, 2};
int  i, j,k = 0;
for (i = 0;i < 2; i++) {
    printf("%d ", *(&b+i));
}

为什么两个code样品表现不同?

why are the two code samples behaving differently?

推荐答案

声明:

int b[2] = {1, 2};

创建两个数组 INT 与值 1 2 。结果
假设在in​​t的系统大小为4个字节,那么阵列 B [] 应存储在内存中类似如下:

Creates an array of two int with values 1, 2.
Suppose in a system size of int is 4-bytes, then the array b[] should be stored in memory something like as follows:

first ele        +----------+                
     (b + 0) ---►|     1    | 0xbf5c787c  <----- &b ,    (c + 0)
next ele         +----------+ 
     (b + 1) ---►|     2    | 0xbf5c7880  <------------- (c + 1)
                 +----------+              
     (b + 2) ---►|     ?    | 0xbf5c7884  <----- (&b + 1) next array  
                 +----------+                    
             ---►|     ?    | 0xbf5c7888  
                 +----------+ 
             ---►|     ?    | 0xbf5c788c  <----- (&b + 2) next array  
                 +----------+      
             ---►|     ?    | 0xbf5c7890
                 +----------+               

? means garbage value
b[] array in memory from 0xbf5c787c to 0xbf5c7880  
each cell is four bytes 

在上面的图表记忆细胞值表示垃圾值和未分配(从 0xbf5c7884 未分配的内存在我们的数组)。值 1 2 的地址存储在内存中 0xbf5c787c 0xbf5c7880 ,即在阵列中分配的 b []

In above diagram memory cells with value ? means garbage values and not allocated (memory from 0xbf5c7884 is not allocated in for our array). The values 1, 2 are stored in memory at address 0xbf5c787c and 0xbf5c7880, that is allocated in array b[].

让我们来代替印刷值,我们打印您使用在code访问(C + I)的内存地址(和b + I),这个考虑下面的程序:

Let's instead of printing values, we print addresses of memory that you access in your code using (c + i) and (&b + i), for this consider following program:

#include<stdio.h>
int main(){
  int b[2] = {1, 2}; 
  int  i = 0;
  int *c = &b; //Give warning: "assignment from incompatible pointer type" 
  printf("\n C address: ");  // outputs correct values 
  for (i = 0; i < 2; i++) {
    printf("%p ", (void*)(c + i));
  }
  printf("\n B address: ");  // outputs incorrect values/ and behaving differently 
  for (i = 0; i < 2; i++) {
    printf("%p ", (void*)(&b + i));  // Undefined behavior 
  }
  return 1;
}

输出:

 C address: 0xbf5c787c 0xbf5c7880 
 B address: 0xbf5c787c 0xbf5c7884 

勾选此code工作@ 结果
请注意,(C + I)打印与价值细胞 1 2 在你第一次code,因此输出是正确的。而(和b + I)打印解决未分配给数组值 B [] (即外阵 b [] )和访问该存储器提供了在运行时未定义行为(UN predictable)。

Check this code working @Codepade
Notice, (c + i) prints correct address of cells with value 1, 2 hence outputs in your first code is correct. Whereas (&b + i) prints address value that is not allocated to array b[] (that is outside of array b[]) And accessing this memory gives undefined behaviour(unpredictable) at runtime.

其实有一个b &放大器之间的的区别; b


  • B 是一个数组,其类型为 INT [2] 衰变为为int * 的地址在大多数前pressions(读第一个元素:some其中,数组名不衰变成一个指针,第一个元素异常?)。和 B + 1 指向数组(注意图)下一 INT 元素。

  • b is an array and its type is int[2], b decays into int* as address for first element in most expressions (read: some exceptions where array name not decaying into a pointer to first element?). And b + 1 points to next int elements in array (notice the diagram).

和b 完成数组的地址和类型是 INT(*)[2] (和b + 1)指向类型的下一个阵列 INT [2]未在分配你的程序(图中通知,其中(和b + 1)点)。

&b is address of complete array and its type is int(*)[2], (&b + 1) points to next array of type int[2] that is not allocated in your program (notice in diagram that where (&b + 1) points).

要知道B之间其他一些有趣的差异和b 阅读:

To know some other interesting differences between b and &b read: What does sizeof(&array) return?

在第一code鹬,当你做 C =和b ,你要在分配数组的地址为int * (在我们的例子 0xbf5c787c )。随着GCC编译器这句话会给警告:从分配不兼容的指针类型结果。
因为 C 是指向 INT ,所以 *(C + I)打印整数存储在地址(C + I)。对于 I = 1 (C + 1)点,第二个元素的数组(在我们的例子在 0xbf5c7880 ),因此 *(C + 1)打印 2 正确。

In first code snipe, when you do c = &b, you are assigning array's address to int* (in our example 0xbf5c787c). With GCC compiler this statement will give warning: "assignment from incompatible pointer type".
Because c is pointer to int, so *(c + i) prints integer stored at address (c + i). For i = 1 the value (c + 1) points to second element in array (in our example at 0xbf5c7880) hence *(c + 1) prints 2 correctly.

关于分配为int * C =和b; 第一code我强烈建议阅读@ AndreyT的的。使用指针会随着访问数组元素的正确的和简单的方法如下:

Regarding assignment int *c = &b; in first code I highly suggest read @AndreyT's answer below. The correct and simple way to access array elements using pointer will be as follows:

int b[2] = {1, 2};
int *c = b;   // removed &, `c` is pointer to int  
int i;
for (i = 0; i < 2; i++){
    printf("%d ", *(c + i)); 
 // printf("%d ", c[i]); // is also correct statement 
}

在你的第二个code,加入 I 和b 使其指向外面分配的内存在printf语句访问使用内存 * 取消引用在运行时该code的操作者会导致无效的内存访问和行为的。这就是code的第二件在不同的执行表现不同的原因。

In your second code, adding i to &b make it pointing to outside allocated memory and in printf statement you access memory using * dereference operator cause invalid memory access and behavior of this code at run time is Undefined. That is the reason that second piece of code behaving differently at different execution.

您code编译,因为它语法正确的,但在未分配的内存运行时访问可以通过操作系统内核检测。今年5月导致操作系统内核发出一个信号,核心转储到引起异常的过程(值得注意:作为操作系统由过程检测内存侵权问题 - 有效内存的无效访问,得出:SIGSEGV,并获得到一个无效的地址给:SIGBUS)。在值得如果你的程序可能会执行无任何故障,并产生垃圾的效果。

Your code compiles because syntactically it correct, But at runtime accessing of unallocated memory can be detected by OS kernel. This may causes OS kernel send a signal core dump to the process which caused the exception (interesting to note: as OS detects memory right violation by a process -- An invalid access to valid memory gives: SIGSEGV, and access to an invalid address gives: SIGBUS). In worth case your program may execute without any failure and produce garbage results.

对于第二个code,使用指针数组将如下打印阵列正确的方法:

Regarding second code, correct way to print array using 'pointer to array' will be as below:

#include<stdio.h>
int main(){
  int b[2] = {1, 2}; 
  int  i;
  int (*c)[2] = &b;   // `c` is pointer to int array of size 2
  for(i = 0; i < 2; i++){
     printf(" b[%d] = (*c)[%d] = %d\n", i, i, (*c)[i]); // notice (*c)[i]
  }
  return 1;
}

输出:

b[0] = (*c)[0] = 1
b[1] = (*c)[1] = 2  

检查@ 。点要注意周围的括号* C 需要为 [] 运算符的precedence高则 * 引用操作(而如果你用指针来诠释你不需要括号如上code)。

Check @codepade. Point to be notice parenthesis around *c is needed as precedence of [] operator is higher then * dereference operator (whereas if you use pointer to int you don't need parentheses as in above code).

这篇关于不一致使用指针,直接一个数组的数组和地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 13:52