2015-03-06 1 views
-3

Ici j'obtiens 4225440 comme l'adresse de arr [0]; comme il s'agit d'un tableau d'entiers, l'adresse sera augmentée de 4, donc la suivante sera 4225444;Pointer Conception

maintenant

  1. ce qui est arrivé à ces adresses
  2. si elles sont mises manualy l'une des adresses, il montre la valeur absurde d'où il vient.

C'est le code en discussion

#include <stdio.h> 

int arr[10],i,a,*j; 
void del(int a); 

main() 
{ 
    for(i=0;i<4;i++) 
     scanf("%d",&arr[i]); 

    j=(int*)4225443; 

    for(i=0;i<4;i++) 
    { 
     printf("\n%d ",arr[i]); 
     printf(" %d ",&arr[i]); 
    } 

    printf(" %d ",*j); 
} 
+0

Dépend de l'architecture du processeur. Cela se bloquerait par exemple dans un processeur ARM, en raison d'un accès non aligné lors de l'impression '* j'. Et bien sûr, à moins de savoir ce qu'il y a à l'adresse 4225443, il est impossible de dire si c'est valide. –

+0

pourquoi nous ne pouvons pas stocker la valeur de arr [1] en 4225441 si arr [0] est en 4225440 –

+0

@MatsPetersson note que certains processeurs ARM ont un support pour l'accès non aligné – ouah

Répondre

-2

Il imprimera valeur, située dans l'adresse 4.225.443, si la valeur existe, sinon elle produira exception de violation de la mémoire.

+0

Je pense que vous voulez dire, si l'accès à cette adresse mémoire est autorisé. Aucune adresse mémoire n'a une valeur qui n'existe pas. –

+0

même pas proche. et le code n'essaie pas d'imprimer le contenu de 4225443. – user3629249

+0

@ user3629249: le code fait d'autres choses aussi, mais pourquoi dites-vous qu'il n'essaie pas d'imprimer le contenu de 4225443? – chqrlie

6
j=(int*)4225443; 
/* ... */ 
printf(" %d ",*j); 

C a son mot à dire:.

(C11, 6.3.2.3p5) « Un entier peut être converti en un type de pointeur Sauf comme précédemment spécifié, le résultat est la mise en oeuvre définie , pourrait ne pas être correctement aligné, ne pas pointer vers une entité du type référencé, et pourrait être une représentation de piège. "

Dans votre cas, vous pouvez ajouter que vous enfreignez également les règles d'alias.

0
most of the CPUs that we use today have either 
a 32bit or 64 bit wide bus between the CPU and the memory. 

Lets use the 32 bit wide bus for demonstration purposes.. 

in general, each memory access will be to read (or write) 32 bits, 
where the first address of that 32 bits will be an address 
that is evenly divisible by 32. 

In such a architecture, a 'int' will start on a address 
that is evenly divisible by 32 and be 4 bytes (32bits) long. 

in general, when the address of 'something' is NOT 
on a 32 bit address boundary 
(I.E. the address is not evenly divisible by 32) 
then the CPU will: 
for read, 
read the whole 32 bits from memory, 
starting at the 32 bit boundary,  
then, within the CPU, 
using the registers and the logic and math operations, 
extract the desired byte. 
for write, 
read the whole 32 bits from memory, 
starting at the 32 bit boundary, 
then, within the CPU, 
using the registers and logic and math operations, 
modify the desired byte, 
then write the whole 32 bits to memory 

In other words, 
accessing memory other than on 32bit boundarys is SLOW. 

Unfortunately some CPUs, 
if requested to read/write some value to/from memory 
at other than a 32 bit boundary will raise a bus error. 

regarding the 'unbelievable' value of the int 
when the second byte of the int is modified... 

A int (lets use a little endian architecture) is 4 bytes, 
aligned on a 32 bit boundary 
(I.E. the lowest address of the int is on a 32 bit boundary.) 

Lets, for example say the int contains '5' 
then its' representation in memory is 0x00,0x00,0x00,0x05 

Then the second byte (address of the int+1) is set to some value, 
for example, say 3, 
Then the int contains 0x000, 0x03, 0x00, 0x05 

now, when that int is printed, it will display: 196613 

Note: the order of the bytes in memory is somewhat different 
     for a big endian architecture.