As all of us already know ->
array[4] == *(array+4) /* BUT */ array[4][4] == ?????
If I have a 2d array like this: array[4][4], how can I access to its elements with pointers notation?
Well just try it out:
| 1 | #include <stdio.h> |
| 2 | |
| 3 | int main(){ |
| 4 | char foo[ 5 ][ 5 ]; |
| 5 | printf( "Foo = %p\n", foo ); |
| 6 | printf( "Foo[0] = %p\n", &foo[ 0 ] ); |
| 7 | printf( "Foo[1] = %p\n", &foo[ 1 ] ); |
| 8 | printf( "Foo[2] = %p\n", &foo[ 2 ] ); |
| 9 | printf( "Foo[3] = %p\n", &foo[ 3 ] ); |
| 10 | |
| 11 | printf( "Foo[0][0] = %p\n", &foo[ 0 ][ 0 ] ); |
| 12 | printf( "Foo[0][1] = %p\n", &foo[ 0 ][ 1 ] ); |
| 13 | printf( "Foo[0][2] = %p\n", &foo[ 0 ][ 2 ] ); |
| 14 | printf( "Foo[0][3] = %p\n", &foo[ 0 ][ 3 ] ); |
| 15 | printf( "Foo[0][4] = %p\n", &foo[ 0 ][ 4 ] ); |
| 16 | printf( "Foo[0][5] = %p\n", &foo[ 0 ][ 5 ] ); |
| 17 | } |
Produces this:
Foo = 0xbffff3f0 Foo[0] = 0xbffff3f0 Foo[1] = 0xbffff3f5 Foo[2] = 0xbffff3fa Foo[3] = 0xbffff3ff Foo[0][0] = 0xbffff3f0 Foo[0][1] = 0xbffff3f1 Foo[0][2] = 0xbffff3f2 Foo[0][3] = 0xbffff3f3 Foo[0][4] = 0xbffff3f4 Foo[0][5] = 0xbffff3f5
You can see that the second index into the first array is exactly N bytes away where N = sizeof(type) * elements in the second array.
but how can I access to its elements with pointer notation?
int array[h][w]; array[y][x] == *(array + y*w + x);
Edit: Sorry, this was a wrong response...
If it's an int **array; that's what you do. But int array[][] isn't the same because it's all one contiguous block in memory. The only pointer is the implicit ones the compiler gives you.
A test:
int main() { int array[1][1]; printf("&array = %p\n&array[0] = %p\n&array[0][0] = %p\n", &array, &array[0], &array[0][0]); return 0; }
gives (with added spacing for ease-of-reading):
&array = 0xbfb44f64 &array[0] = 0xbfb44f64 &array[0][0] = 0xbfb44f64
Thank you Kitticat, that was really helpful!!!
Well I really suck at strings manipulations, look a this
| 1 | /* CONSOLE APPLICATION*/ |
| 2 | #include <stdio.h> |
| 3 | #include <conio.h> |
| 4 | |
| 5 | void main (void) |
| 6 | { |
| 7 | /* Prototipos de funciones */ |
| 8 | void carga_datos(char nya[6][20], float *notas); |
| 9 | char nombres [6][20]; |
| 10 | float notas[6][20]; |
| 11 | carga_datos(nombres, notas); |
| 12 | |
| 13 | } |
| 14 | |
| 15 | void carga_datos(char nya[6][20], float *notas) |
| 16 | { |
| 17 | int i=0; |
| 18 | char coco[20]; |
| 19 | do{ |
| 20 | printf("\nEnter name :"); |
| 21 | fflush(stdin); |
| 22 | scanf("%s",&nya<i>[0]); |
| 23 | i++; |
| 24 | }while(i<6); |
| 25 | |
| 26 | getch(); |
| 27 | |
| 28 | /* now show the strtings*/ |
| 29 | i=0; |
| 30 | do{ |
| 31 | printf("\nName :%s",nya[0][0]); /*<-ERROR HERE*/ |
| 32 | i++; |
| 33 | }while(i<6); |
| 34 | getch(); |
| 35 | |
| 36 | } |
I get an error in the marked line, What the heck am I doing wrong?
I am going to make 2 versions of this stupid program, one with indexes, and the other one with pointer notation, however I can't code the easy one with indexes
I refuse to help anyone using conio.h 
Just teasing. You should be using something like printf("\nName :%s",(char *)(nya[0]));, maybe printf("\nName :%s",(char *)(&nya[0]));, although I am not sure which one is correct.
You're passing a char, but it's expecting a pointer to a char. You'd pass nya[0] (or it looks like you meant nya[i]), which will give a pointer to the string.
Master Rey, you know all the answers as usual!!!
Thats works, I am going to KILL my teacher, 
You're passing a char, but it's expecting a pointer to a char. You'd pass nya(0) (or it looks like you meant nya(i)), which will give a pointer to the string.
Well, so I have to omit the second index, now I think pointer notation is easier than indexes:P
EDIT:
&nya[5][5] is a pointer to a char(a 2d pointer?)
nya[5][5] is a char
nya[5] is a pointer to a char
isn't a bit confusing? now I really think pointer notation is easier.
&nya[5][5] is a pointer to a char(a 2d pointer?)
Not really. This is no different than in the following snippet:
int *ptr, value; ptr = &value;
ptr is the pointer. We can point ptr at value though by assigning the address of value (&value) to it. Similarly, you can assign &nya[5][5] to a pointer. Or &nya[5] (or even &nya).
nya[5][5] is a char
nya[5] is a pointer to a char
If you think of nya[5] as not just being a pointer to a char, but a pointer to an array of chars, it makes more sense.
Finally finished, I didn't follow KittiCat way exactly, but it works the same.
| 1 | #include <stdio.h> |
| 2 | #include <conio.h> |
| 3 | #include <string.h> /* Solo se usa para strcpy */ |
| 4 | #include <stdlib.h> /* Solo se usa para exit */ |
| 5 | |
| 6 | #define nya_fil 6 /* Cant. de filas para el array nya (nombre y appellido) */ |
| 7 | #define nya_col 20 /* Cant. de columnas para el arrya nya (nombre y appellido) */ |
| 8 | #define notas_fil 6 /* Cant. de filas para el array de notas */ |
| 9 | #define notas_col 7 /* Cant. de coumnas para el array de notas (6 notas + promedio = 7)*/ |
| 10 | |
| 11 | /* Struct para grabar a archivo */ |
| 12 | struct _alumno { |
| 13 | char nya[20]; |
| 14 | float promedio; |
| 15 | } _alumno; |
| 16 | |
| 17 | /* Usado para volcar los datos desde las matrices y grabar el archivo */ |
| 18 | struct _alumno alumnos[6]; |
| 19 | /* Usado para verificacion, permanecera vacio, se cargara solo con los valores leidos desde archivo */ |
| 20 | struct _alumno alumnos_archivo[6]; |
| 21 | |
| 22 | /*------------------------------------------ MAIN --------------------------------------------- */ |
| 23 | void main (void) |
| 24 | { |
| 25 | /* Puntero para archivo */ |
| 26 | FILE *archivo; |
| 27 | |
| 28 | /* Prototipos de funcione */ |
| 29 | float promedio(float *notas, int alumno); |
| 30 | |
| 31 | /* 1ro filas, luego columnas, array[filas][columans] */ |
| 32 | char _nya [nya_fil][nya_col]; |
| 33 | float _notas[notas_fil][notas_col]; |
| 34 | |
| 35 | char *nya = _nya; |
| 36 | float *notas = _notas; |
| 37 | |
| 38 | /* Cargo los nombres y apellidos primero */ |
| 39 | int i=0,j=0,k=0,l=0; |
| 40 | for(i=0; i<(nya_fil*nya_col); i+=nya_col) { |
| 41 | printf("Enter name and surname ->"); |
| 42 | fflush(stdin); |
| 43 | gets(nya+i); |
| 44 | *(nya+i+19)='\0'; /* No dejo ingresar mas de 20 caracteres */ |
| 45 | |
| 46 | /* Linea agregada para grabar datos a struct */ |
| 47 | strcpy(alumnos[j].nya, nya+i); j++; |
| 48 | } |
| 49 | getch(); |
| 50 | |
| 51 | /* Ahora cargo las 6 notas y calculo el promedio */ |
| 52 | j=0; |
| 53 | for(i=0; i<(nya_fil*nya_col); i+=nya_col){ |
| 54 | for(k=0; k<6; k++){ |
| 55 | printf("Enter score number %d, for student %s ->",k+1, nya+i); |
| 56 | fflush(stdin); |
| 57 | scanf("%f",notas+j+k); |
| 58 | } |
| 59 | /* En la 7ma posicion del la matriz le mando el promedio llamando a funcion */ |
| 60 | *(notas+j+k)=promedio(notas,j); |
| 61 | |
| 62 | /* Linea agregada para grabar datos a struct */ |
| 63 | alumnos[l].promedio = *(notas+j+k); l++; |
| 64 | |
| 65 | /* Salto al siguiente alumno */ |
| 66 | j+=notas_col; |
| 67 | } |
| 68 | getch(); |
| 69 | |
| 70 | /* PUNTO A. Muestrto los datos ingresados tal como lo pide el ejercicio */ |
| 71 | j=0; |
| 72 | printf("\nNAME AND SURNAME SCORES AVERAGE\n"); |
| 73 | for(i=0; i<(nya_fil*nya_col); i+=nya_col){ //Recorro array de nombres |
| 74 | printf("%-20s %.1f %.1f %.1f %.1f %.1f %.1f %.1f \n",nya+i,*(notas+j),*(notas+j+1),*(notas+j+2),*(notas+j+3),*(notas+j+4),*(notas+j+5),*(notas+j+6)); |
| 75 | j+=notas_col; |
| 76 | } |
| 77 | printf("\nPress a key to save data . . ."); |
| 78 | getch(); |
| 79 | |
| 80 | /* PUNTO B. Grabamo todo a archivo */ |
| 81 | archivo = fopen("ALUMNOS.DAT", "wb"); /* Abro archivo para escritura */ |
| 82 | if(!archivo) exit (printf("File Error")); |
| 83 | for(i=0; i<6; i++) { |
| 84 | fwrite(&alumnos, sizeof(alumnos), 1, archivo); |
| 85 | } |
| 86 | fclose(archivo); |
| 87 | |
| 88 | printf("\nFile saved."); |
| 89 | printf("\nPress a key for loading data from file. . .\n"); |
| 90 | getch(); |
| 91 | |
| 92 | archivo = fopen("ALUMNOS.DAT", "rb"); /* Abro archivo para lectura */ |
| 93 | for(i=0; i<6; i++) { |
| 94 | /* Cargo los datos del archivo al array vacio que he reservado */ |
| 95 | fread(&alumnos_archivo, sizeof(alumnos_archivo), 1, archivo); |
| 96 | printf("\nAverage : %.1f , student %s",alumnos_archivo<i>.promedio, alumnos_archivo<i>.nya); |
| 97 | getch(); |
| 98 | } |
| 99 | fclose(archivo);getch(); |
| 100 | } |
| 101 | |
| 102 | /*------------------------------------- PROMEDIO == AVERAGE -------------------------------------------*/ |
| 103 | float promedio(float *notas, int alumno){ |
| 104 | int i; |
| 105 | float sumatoria=0; |
| 106 | for(i=0;i<6;i++){ |
| 107 | sumatoria+=*(notas+i+alumno); |
| 108 | } |
| 109 | sumatoria = sumatoria/(notas_col-1); |
| 110 | return sumatoria; |
| 111 | } |
EDIT: I NEED HELP
I am getting 2 warinings, I am using Borland C++5.0 compiler (win16 console app), but a friend of mine obtained 2 errors instead, compiling with Borland C++5.2.
These are the lines:
(36, 5) Suspicious pointer conversion
(38, 8) Suspicious pointer conversion
Dont use pointers if you dont have to.
Optimzing compilers can do as good or better job of arrays using normal notation (due to aliasing issues)
int array[h][w];
array[y][x] == *(array + y*w + x);
what about array[y][x] == *( (*(array + y)) + x); instead?
AE.
array[y][x] == *( (*(array + y)) + x);
With a static 2d array will cause a compile error. array+y will give you &array[0][y] (remember, an array != a pointer. the only pointer you get from an array is an implicit one from the compiler), deref that and add x, you modify the value at [0][y], and get an int. Try to deref that, and the compiler will error on you. Try to force it with a cast, and you'll more than likely sigsegv.
I am getting 2 warinings . . .
These are the lines:
(36, 5) Suspicious pointer conversion
(38, 8) Suspicious pointer conversion
char *nya = _nya; /* wrong */ char *nya = _nya[0]; /* right */
Fixed!
Dont use pointers if you dont have to.
Optimzing compilers can do as good or better job of arrays using normal notation (due to aliasing issues)
We are forced to use pointer notation in our exams, if we don't, we get disqualified.
I always thought that a 2D array was a pointer to an array of pointers into the data. I've written some code that allocates dynamic 2D arrays. First, it allocates a block of memory equivalent to ysize*xsize*datasize, and then it allocates a separate 1D array equivalent to ysize*sizeof(void). This separate array is filled to point to each row of xsize*datasize bytes. The resulting array can be accessed using normal 2D array notation.
AE.
A pointer is a pointer , and an array is an array. int **ptr; is a pointer to a pointer, and int array[foo][bar]; is an array of foo*bar elements. A pointer can point to an array, but a pointer is not an array.