Accesing 2d arrays with pointer notation
Paul whoknows

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?

kazzmir

Well just try it out:

1#include <stdio.h>
2 
3int 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.

Paul whoknows

but how can I access to its elements with pointer notation?

Kitty Cat
int array[h][w];
array[y][x] == *(array + y*w + x);

Carrus85

Edit: Sorry, this was a wrong response...

Kitty Cat

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

Paul whoknows

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 
5void main (void)
6{
7/* Prototipos de funciones */
8void carga_datos(char nya[6][20], float *notas);
9char nombres [6][20];
10float notas[6][20];
11carga_datos(nombres, notas);
12 
13}
14 
15void carga_datos(char nya[6][20], float *notas)
16{
17int i=0;
18char coco[20];
19do{
20 printf("\nEnter name :");
21 fflush(stdin);
22 scanf("%s",&nya<i>[0]);
23 i++;
24}while(i<6);
25 
26getch();
27 
28/* now show the strtings*/
29i=0;
30do{
31 printf("\nName :%s",nya[0][0]); /*<-ERROR HERE*/
32 i++;
33}while(i<6);
34getch();
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

:-/

ReyBrujo

I refuse to help anyone using conio.h :P

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.

Kitty Cat

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.

Paul whoknows

Master Rey, you know all the answers as usual!!!
Thats works, I am going to KILL my teacher, ;D

Quote:

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.

LennyLen
Quote:

&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).

Quote:

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.

Paul whoknows

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 */
12struct _alumno {
13 char nya[20];
14 float promedio;
15} _alumno;
16 
17/* Usado para volcar los datos desde las matrices y grabar el archivo */
18struct _alumno alumnos[6];
19/* Usado para verificacion, permanecera vacio, se cargara solo con los valores leidos desde archivo */
20struct _alumno alumnos_archivo[6];
21 
22/*------------------------------------------ MAIN --------------------------------------------- */
23void main (void)
24{
25/* Puntero para archivo */
26FILE *archivo;
27 
28/* Prototipos de funcione */
29float promedio(float *notas, int alumno);
30 
31/* 1ro filas, luego columnas, array[filas][columans] */
32char _nya [nya_fil][nya_col];
33float _notas[notas_fil][notas_col];
34 
35char *nya = _nya;
36float *notas = _notas;
37 
38/* Cargo los nombres y apellidos primero */
39int i=0,j=0,k=0,l=0;
40for(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}
49getch();
50 
51/* Ahora cargo las 6 notas y calculo el promedio */
52j=0;
53for(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}
68getch();
69 
70/* PUNTO A. Muestrto los datos ingresados tal como lo pide el ejercicio */
71j=0;
72printf("\nNAME AND SURNAME SCORES AVERAGE\n");
73for(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}
77printf("\nPress a key to save data . . .");
78getch();
79 
80/* PUNTO B. Grabamo todo a archivo */
81archivo = fopen("ALUMNOS.DAT", "wb"); /* Abro archivo para escritura */
82if(!archivo) exit (printf("File Error"));
83for(i=0; i<6; i++) {
84 fwrite(&alumnos, sizeof(alumnos), 1, archivo);
85}
86fclose(archivo);
87 
88printf("\nFile saved.");
89printf("\nPress a key for loading data from file. . .\n");
90getch();
91 
92archivo = fopen("ALUMNOS.DAT", "rb"); /* Abro archivo para lectura */
93for(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}
99fclose(archivo);getch();
100}
101 
102/*------------------------------------- PROMEDIO == AVERAGE -------------------------------------------*/
103float promedio(float *notas, int alumno){
104int i;
105float sumatoria=0;
106for(i=0;i<6;i++){
107 sumatoria+=*(notas+i+alumno);
108}
109sumatoria = sumatoria/(notas_col-1);
110return 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

A J

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)

Andrei Ellman
Kitty Cat said:

int array[h][w];
array[y][x] == *(array + y*w + x);

what about array[y][x] == *( (*(array + y)) + x); instead?

AE.

Kitty Cat

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.

Paul whoknows
Quote:

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!

Quote:

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.

Andrei Ellman

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.

Kitty Cat

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.

Thread #583086. Printed from Allegro.cc