¿Por qué la indexación comienza con cero en 'C'?


154

¿Por qué la indexación en una matriz comienza con cero en C y no con 1?


77
¡Se trata de punteros!
medopal


3
Un puntero (matriz) es una dirección de memoria y el índice es un desplazamiento de esa dirección de memoria, por lo que el primer elemento del puntero (matriz) es el que la compensación es igual a 0.
D33pN16h7

3
@drhirsch porque cuando contamos un conjunto de objetos, comenzamos señalando un objeto y diciendo "uno".
phoog

1
Los estadounidenses cuentan los pisos (pisos) de un edificio desde uno en la planta baja; los británicos cuentan desde cero (planta baja), subiendo al primer piso, luego al segundo piso, etc.
Jonathan Leffler

Respuestas:


116

En C, el nombre de una matriz es esencialmente un puntero [pero vea los comentarios] , una referencia a una ubicación de memoria, por lo que la expresión se array[n]refiere a nelementos de ubicación de memoria alejados del elemento inicial. Esto significa que el índice se usa como un desplazamiento. El primer elemento de la matriz está contenido exactamente en la ubicación de la memoria a la que se refiere la matriz (0 elementos de distancia), por lo que debe indicarse como array[0].

Para más información:

http://developeronline.blogspot.com/2008/04/why-array-index-should-start-from-0.html


20
El nombre de una matriz es el nombre de la matriz; Contrariamente a la idea errónea común, las matrices no son punteros en ningún sentido. Una expresión de matriz (como el nombre de un objeto de matriz) generalmente, pero no siempre , se convierte en un puntero al primer elemento. Ejemplo: sizeof arrproduce el tamaño del objeto de matriz, no el tamaño de un puntero.
Keith Thompson

Si bien es obvio que no ha reaccionado a @ comentario de KeithThompson, me gustaría utiliza un curso más ofensiva: " En C, el nombre de una matriz es esencialmente un puntero, una referencia a una ubicación de memoria " - No, es no . Al menos no en un punto de vista genérico. Si bien su respuesta perfecta responde a la pregunta de una manera en que 0 como inicio de índice es importante, la primera oración es simplemente incorrecta. Una matriz no siempre se descompone en un puntero a su primer elemento.
RobertS apoya a Monica Cellio el

Cita del estándar C, (C18), 6.3.2.1/4: " Excepto cuando es el operando del sizeofoperador, o el &operador unario , o es un literal de cadena utilizado para inicializar una matriz, una expresión que tiene tipo" matriz de tipo "se convierte en una expresión con el tipo" puntero para escribir "que apunta al elemento inicial del objeto de matriz y no es un valor. Si el objeto de matriz tiene una clase de almacenamiento de registro, el comportamiento es indefinido. "
RobertS admite a Monica Cellio 01 de

Además, esta descomposición se produce de una manera más "implícita" o "formal" que la sugerida aquí; no hay descomposición de un objeto puntero en la memoria involucrada. Este es el objeto de esta pregunta: ¿se cambia la matriz a la disminución del puntero a un objeto puntero? - Edite su respuesta para que sea completamente correcta.
RobertS apoya a Monica Cellio el

103

Esta pregunta fue publicada hace más de un año, pero aquí va ...


Sobre las razones anteriores

Si bien el artículo de Dijkstra (mencionado anteriormente en una respuesta ahora eliminada ) tiene sentido desde una perspectiva matemática, no es tan relevante cuando se trata de programación.

La decisión tomada por la especificación del lenguaje y los diseñadores del compilador se basa en la decisión tomada por los diseñadores de sistemas informáticos de comenzar a contar en 0.


La probable razon

Citando de una súplica por la paz por Danny Cohen.

Para cualquier base b, los primeros enteros no negativos b ^ N están representados por exactamente N dígitos (incluidos los ceros a la izquierda) solo si la numeración comienza en 0.

Esto se puede probar con bastante facilidad. En base-2, toma 2^3 = 8 El octavo número es:

  • 8 (binario: 1000) si comenzamos a contar en 1
  • 7 (binario: 111) si comenzamos a contar en 0

111se puede representar usando 3bits, mientras 1000que requerirá un bit adicional (4 bits).


¿Por qué es esto relevante?

Las direcciones de memoria de la computadora tienen 2^Nceldas direccionadas por Nbits. Ahora, si comenzamos a contar en 1, las 2^Nceldas necesitarían N+1líneas de dirección. Se necesita el bit extra para acceder exactamente a 1 dirección. ( 1000en el caso anterior). Otra forma de resolverlo sería dejar la última dirección inaccesible y usar Nlíneas de dirección.

Ambas son soluciones subóptimas , en comparación con el recuento inicial en 0, que mantendría todas las direcciones accesibles, ¡usando exactamente Nlíneas de dirección!


Conclusión

La decisión de comenzar a contar 0desde entonces ha permeado todos los sistemas digitales , incluido el software que se ejecuta en ellos, porque simplifica la traducción del código a lo que el sistema subyacente puede interpretar. Si no fuera así, habría una operación de traducción innecesaria entre la máquina y el programador, para cada acceso a la matriz. Hace que la compilación sea más fácil.


Citando del periódico:

ingrese la descripción de la imagen aquí


2
¿Qué pasaría si
acabaran de

2
¿Estás sugiriendo realmente la modificación de la aritmética básica para que encaje? ¿No crees que lo que tenemos hoy es una solución mucho mejor?
Anirudh Ramanathan

Años después mis 2 cnt valieron. En mi experiencia (~ 35 años de programación) el módulo o la operación de adición modular de una forma u otra surge sorprendentemente a menudo. Con base cero, el siguiente en secuencia es (i + 1)% n pero con base 1 viene (i-1)% n) +1, por lo que creo que se prefiere 0 basado. Esto surge en matemáticas y programación con bastante frecuencia. Tal vez sea solo yo o el campo en el que trabajo.
nyholku

Si bien todas las razones buenas creo que es mucho más simple: a[b]se implementan como *(a+b)en los primeros compiladores. Incluso hoy todavía puedes escribir en 2[a]lugar de a[2]. Ahora, si los índices no comenzaran en 0, a[b]se convertirían en *(a+b-1). Esto habría requerido 2 adiciones en las CPU del tiempo en lugar de 0, lo que significa la mitad de la velocidad. Claramente no es deseable.
Goswin von Brederlow

1
El hecho de que desee 8 estados, no significa que debe tener el número 8 en ellos. Los interruptores de luz en mi casa están felices de representar estados de "luz encendida", "luz apagada", sin preguntarse nunca por qué no representan el número 2.
Spyryto

27

Porque 0 es qué tan lejos del puntero a la cabeza de la matriz al primer elemento de la matriz.

Considerar:

int foo[5] = {1,2,3,4,5};

Para acceder a 0 hacemos:

foo[0] 

Pero foo se descompone en un puntero, y el acceso anterior tiene una forma aritmética de puntero análogo para acceder a él.

*(foo + 0)

En estos días, la aritmética de puntero no se usa con tanta frecuencia. Sin embargo, en el pasado, era una forma conveniente de tomar una dirección y alejar X "ints" de ese punto de partida. Por supuesto, si quisieras quedarte donde estás, ¡solo agregas 0!


23

Porque el índice basado en 0 permite ...

array[index]

... para ser implementado como ...

*(array + index)

Si el índice estuviera basado en 1, el compilador necesitaría generar:, *(array + index - 1)y este "-1" dañaría el rendimiento.


44
Muestras un punto de vista interesante. Puede dañar el rendimiento. Pero, ¿será significativo el rendimiento para justificar el uso de 0 como índice inicial? Lo dudo.
Nombre Apellido

3
@FirstNameLastName Los índices basados ​​en 1 no ofrecen ninguna ventaja sobre los índices basados ​​en 0, pero tienen un rendimiento (ligeramente) peor. Eso justifica los índices basados ​​en 0 sin importar cuán "pequeña" sea la ganancia. Incluso si los índices basados ​​en 1 ofrecen alguna ventaja, el espíritu de C ++ es elegir el rendimiento en lugar de la conveniencia. C ++ a veces se usa en contextos donde importa hasta el último bit de rendimiento, y estas cosas "pequeñas" pueden sumar rápidamente.
Branko Dimitrijevic

Sí, entiendo que las cosas pequeñas pueden acumularse y, a veces, convertirse en algo grande. Por ejemplo, $ 1 por año no es mucho dinero. Pero, si 2 mil millones de personas lo donan, entonces podemos hacer mucho bien por la humanidad. Estoy buscando un ejemplo similar en la codificación que podría causar un bajo rendimiento.
Nombre Apellido

2
En lugar de restar 1, debe usar la dirección de la matriz-1 como la dirección base. Eso es lo que hicimos en un compilador en el que trabajé una vez. Eso elimina la resta de tiempo de ejecución. Cuando escribes un compilador, esas instrucciones adicionales son muy importantes. El compilador se usará para generar miles de programas, cada uno de los cuales se puede usar miles de veces, y esa instrucción adicional 1 puede ocurrir en varias líneas dentro de un bucle n cuadrado. Puede sumar miles de millones de ciclos desperdiciados.
programa

No, no dañará el rendimiento una vez que se compila, solo agregará un pequeño tiempo de compilación porque al final se traducirá al código de la máquina. Solo dañará a los diseñadores del compilador.
Hassaan Akbar

12

Porque simplificó el compilador y el enlazador (más fácil de escribir).

Referencia :

"... Hacer referencia a la memoria mediante una dirección y un desplazamiento se representa directamente en el hardware en prácticamente todas las arquitecturas de computadora, por lo que este detalle de diseño en C facilita la compilación"

y

"... esto hace que la implementación sea más simple ..."


1
+1 No estoy seguro de por qué los votos negativos. Si bien no responde directamente a la pregunta, la indexación basada en 0 no es natural para las personas o los matemáticos; la única razón por la que se hace es porque la implementación es lógicamente consistente (simple).
phkahler

44
@phkahler: el error está en autores e idiomas que llaman índices de matriz como índices; Si lo considera como un desplazamiento, entonces el basado en 0 también se vuelve natural para los legos. Considere el reloj, el primer minuto está escrito como 00:00, no 00:01 ¿no?
Lie Ryan

3
+1: esta es probablemente la respuesta más correcta. C es anterior al documento de Djikistras y fue uno de los primeros idiomas "start at 0". C comenzó su vida "como un ensamblador de alto nivel" y es probable que K&R quisiera apegarse tanto a la forma en que se hizo en el ensamblador donde normalmente tendría una dirección base más un desplazamiento que comienza en cero.
James Anderson

Pensé que la pregunta era por qué se utilizó 0 basado, no cuál es mejor.
programa

2
No votaré negativamente, pero como el programa comentado anteriormente, la base se puede solucionar ajustando la dirección de las matrices, así que independientemente del tiempo de ejecución de la base es el mismo y esto es trivial de implementar en el compilador o en el intérprete, por lo que no hace que la implementación sea más simple . Testigo Pascal donde puede utilizar cualquier rango para indexar IIRC, han pasado 25 años;)
nyholku

5

El índice de matriz siempre comienza con cero. Supongamos que la dirección base es 2000. Ahora arr[i] = *(arr+i). Ahora if i= 0, esto significa *(2000+0) es igual a la dirección base o la dirección del primer elemento en la matriz. este índice se trata como desplazamiento, por lo que el índice predeterminado comienza desde cero.


5

Por la misma razón que, cuando es miércoles y alguien te pregunta cuántos días hasta el miércoles, dices 0 en lugar de 1, y que cuando es miércoles y alguien te pregunta cuántos días hasta el jueves, dices 1 en lugar de 2.


66
Su respuesta parece solo una cuestión de opinión.
heltonbiker

66
Bueno, es lo que hace que agregar índices / compensaciones funcione. Por ejemplo, si "hoy" es 0 y "mañana" es 1, "mañana de mañana" es 1 + 1 = 2. Pero si "hoy" es 1 y "mañana" es 2, "mañana de mañana" no es 2 + 2. En las matrices, este fenómeno ocurre siempre que desee considerar un subrango de una matriz como una matriz por derecho propio.
R .. GitHub DEJA DE AYUDAR AL HIELO

77
Llamar a una colección de 3 cosas "3 cosas" y numerarlas 1,2,3 no es una deficiencia. Numerarlos con un desplazamiento del primero no es natural, incluso en matemáticas. El único momento en que indexa desde cero en matemáticas es cuando desea incluir algo como la potencia cero (término constante) en un polinomio.
phkahler

9
Re: "Las matrices de numeración que comienzan con 1 en lugar de 0 son para personas con una deficiencia severa de pensamiento matemático". Mi edición de "Introducción a los algoritmos" de CLR utiliza la indexación de matriz basada en 1; No creo que los autores tengan una deficiencia en el pensamiento matemático.
RexE

No, yo diría que el séptimo está en el índice 6, o 6 posiciones lejos del primero.
R .. GitHub DEJA DE AYUDAR A ICE

2

La explicación más elegante que he leído para la numeración basada en cero es una observación de que los valores no se almacenan en los lugares marcados en la línea numérica, sino en los espacios entre ellos. El primer elemento se almacena entre cero y uno, el siguiente entre uno y dos, etc. El enésimo elemento se almacena entre N-1 y N. Se puede describir un rango de elementos utilizando los números a cada lado. Los artículos individuales se describen por convención usando los números debajo de él. Si a uno se le asigna un rango (X, Y), la identificación de números individuales usando el número a continuación significa que se puede identificar el primer elemento sin usar ninguna aritmética (es el elemento X), pero se debe restar uno de Y para identificar el último elemento (Y -1). Identificar los elementos con el número anterior facilitaría la identificación del último elemento de un rango (sería el elemento Y)

Aunque no sería horrible identificar elementos basados ​​en el número que se encuentra sobre ellos, definir el primer elemento en el rango (X, Y) como el que está arriba de X generalmente funciona mejor que definirlo como el siguiente (X + 1)


1

La razón técnica podría derivarse del hecho de que el puntero a una ubicación de memoria de una matriz es el contenido del primer elemento de la matriz. Si declara el puntero con un índice de uno, los programas normalmente agregarían ese valor de uno al puntero para acceder al contenido que no es lo que desea, por supuesto.


1

Intente acceder a una pantalla de píxeles utilizando las coordenadas X, Y en una matriz basada en 1. La fórmula es completamente compleja. ¿Por qué es complejo? Debido a que terminas convirtiendo las coordenadas X, Y en un número, el desplazamiento. ¿Por qué necesita convertir X, Y en un desplazamiento? Porque así es como se organiza la memoria dentro de las computadoras, como un flujo continuo de celdas de memoria (matrices). ¿Cómo se ocupan las computadoras con las células de la matriz? Uso de desplazamientos (desplazamientos desde la primera celda, un modelo de indexación basado en cero).

Entonces, en algún punto del código que necesita (o el compilador necesita) para convertir la fórmula de 1 base en una fórmula basada en 0 porque así es como las computadoras manejan la memoria.


1

Supongamos que queremos crear una matriz de tamaño 5
int array [5] = [2,3,5,9,8]

dejemos que el primer elemento de la matriz apunte a la ubicación 100

y consideremos que la indexación comienza desde 1 no desde 0.

ahora tenemos que encontrar la ubicación del primer elemento con la ayuda del índice
(recuerde que la ubicación del primer elemento es 100)

ya que el tamaño de un entero es de 4 bits,
por lo tanto -> considerando el índice 1, la posición sería el
tamaño del índice (1) * tamaño del entero (4) = 4,
por lo que la posición real que nos mostrará es

100 + 4 = 104

lo cual no es cierto porque la ubicación inicial era 100.
Debería apuntar a 100, no a 104,
esto está mal

Supongamos que hemos tomado la indexación desde 0,
entonces la
posición del primer elemento debe ser el
tamaño del índice (0) * tamaño del entero. (4) = 0

por lo tanto -> la
ubicación del primer elemento es 100 + 0 = 100

y esa fue la ubicación real del elemento,
esta es la razón por la cual la indexación comienza en 0;

Espero que aclare tu punto.


1

Soy de un fondo Java. He presentado la respuesta a esta pregunta en el diagrama a continuación que he escrito en un papel que se explica por sí mismo.

Pasos principales:

  1. Crear referencia
  2. Instanciación de matriz
  3. Asignación de datos a la matriz

  • También tenga en cuenta cuando la matriz se instancia solo ... Cero se asigna a todos los bloques de forma predeterminada hasta que le asignemos un valor
  • La matriz comienza con cero porque la primera dirección apuntará a la referencia (i: e - X102 + 0 en la imagen)

ingrese la descripción de la imagen aquí

Nota : Los bloques que se muestran en la imagen son representaciones de la memoria.


0

En primer lugar, debe saber que las matrices se consideran internamente como punteros porque el "nombre de la matriz contiene la dirección del primer elemento de la matriz".

ex. int arr[2] = {5,4};

considere que la matriz comienza en la dirección 100, por lo que el primer elemento estará en la dirección 100 y la segunda en 104 ahora, considere que si el índice de la matriz comienza en 1, entonces

arr[1]:-

esto se puede escribir en la expresión de punteros como esta:

 arr[1] = *(arr + 1 * (size of single element of array));

considere el tamaño de int es 4bytes, ahora,

arr[1] = *(arr + 1 * (4) );
arr[1] = *(arr + 4);

como sabemos, el nombre de la matriz contiene la dirección de su primer elemento, así que arr = 100 ahora,

arr[1] = *(100 + 4);
arr[1] = *(104);

lo que da,

arr[1] = 4;

Debido a esta expresión, no podemos acceder al elemento en la dirección 100, que es el primer elemento oficial,

ahora considere que el índice de matriz comienza desde 0, entonces

arr[0]:-

esto se resolverá como

arr[0] = *(arr + 0 + (size of type of array));
arr[0] = *(arr + 0 * 4);
arr[0] = *(arr + 0);
arr[0] = *(arr);

ahora, sabemos que el nombre de la matriz contiene la dirección de su primer elemento, entonces,

arr[0] = *(100);

que da el resultado correcto

arr[0] = 5;

por lo tanto, el índice de matriz siempre comienza desde 0 en c.

referencia: todos los detalles están escritos en el libro "El lenguaje de programación C de brian kerninghan y dennis ritchie"


0

En la matriz, el índice indica la distancia desde el elemento inicial. Entonces, el primer elemento está a 0 distancia del elemento inicial. Entonces, es por eso que la matriz comienza desde 0.


0

Es porque addresstiene que apuntar a la derecha elementen la matriz. Asumamos la siguiente matriz:

let arr = [10, 20, 40, 60]; 

Consideremos ahora el inicio de la dirección 12y el tamaño del elementser 4 bytes.

address of arr[0] = 12 + (0 * 4) => 12
address of arr[1] = 12 + (1 * 4) => 16
address of arr[2] = 12 + (2 * 4) => 20
address of arr[3] = 12 + (3 * 4) => 24

Si no fuera así zero-based , técnicamente nuestra primera dirección de elemento en el arraysería la 16que está mal como es su ubicación 12.


-2

El nombre de la matriz es un puntero constante que apunta a la dirección base. Cuando usa arr [i], el compilador lo manipula como * (arr + i). Dado que el rango int es -128 a 127, el compilador piensa que -128 a -1 son los números negativos y del 0 al 128 son números positivos, por lo que el índice de matriz siempre comienza con cero.


1
¿Qué quiere decir con 'rango int es -128 a 127' ? Se intrequiere un tipo para admitir al menos un rango de 16 bits, y en la mayoría de los sistemas actualmente admite 32 bits. Creo que su lógica es defectuosa, y su respuesta realmente no mejora en las otras respuestas ya proporcionadas por otras personas. Sugiero eliminar esto.
Jonathan Leffler
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.