vectores punteros programacion matriz matrices llenar funciones ejemplos con como codigo clase c++ arrays language-lawyer pointer-arithmetic ptrdiff-t

c++ - programacion - ¿Puede ptrdiff_t representar todas las restas de punteros a elementos del mismo objeto de matriz?



vectores en c++ pdf (2)

¿Es posible incluso que el resultado de ij no esté en el rango de valores representables de ptrdiff_t ?

Sí, pero es poco probable.

De hecho, [support.types.layout]/2 no dice mucho, excepto que las reglas apropiadas sobre la resta de punteros y ptrdiff_t se definen en [expr.add] . Así que veamos esta sección.

[expr.add]/5

Cuando se restan dos punteros a elementos del mismo objeto de matriz, el tipo de resultado es un tipo integral con signo definido por la implementación; este tipo será del mismo tipo que se define como std​::​ptrdiff_t en el encabezado <cstddef> .

En primer lugar, tenga en cuenta que el caso donde i y j son índices subíndices de diferentes matrices no se considera. Esto permite tratar ij como PQ donde P es un puntero al elemento de una matriz en el subíndice i Q es un puntero al elemento de la misma matriz en el subíndice j . De hecho, restar dos punteros a elementos de diferentes matrices es un comportamiento indefinido :

[expr.add]/5

Si las expresiones P y Q apuntan, respectivamente, a los elementos x[i] y x[j] del mismo objeto de matriz x , la expresión P - Q tiene el valor i−j ; de lo contrario, el comportamiento no está definido .

Como conclusión, con la notación definida anteriormente, ij y PQ se definen para tener el mismo valor, siendo este último del tipo std::ptrdiff_t . Pero no se dice nada sobre la posibilidad de que este tipo tenga tal valor. Sin embargo, esta pregunta puede responderse con la ayuda de std::numeric_limits ; especialmente, uno puede detectar si una matriz some_array es demasiado grande para std::ptrdiff_t para contener todas las diferencias de índice:

static_assert(std::numeric_limits<std::ptrdiff_t>::max() > sizeof(some_array)/sizeof(some_array[0]), "some_array is too big, subtracting its first and one-past-the-end element indexes " "or pointers would lead to undefined behavior as per [expr.add]/5." );

Ahora, en el objetivo habitual, esto normalmente no ocurriría como sizeof(std::ptrdiff_t) == sizeof(void*) ; lo que significa que una matriz debería ser estúpidamente grande para que ptrdiff_t desborde. Pero no hay garantía de eso.

Para la resta de punteros i y j a elementos del mismo objeto de matriz, la nota en [expr.add # 5] dice:

[ Nota: si el valor i-j no está en el rango de valores representables de tipo std​::​ptrdiff_t , el comportamiento no está definido. - nota final ]

Pero dado [support.types.layout#2] , que establece que (el énfasis es mío):

  1. El tipo ptrdiff_t es un tipo de entero con signo definido por la implementación que puede contener la diferencia de dos subíndices en un objeto de matriz, como se describe en [expr.add] .

¿Es posible incluso que el resultado de ij no esté en el rango de valores representables de ptrdiff_t ?

PD: Me disculpo si mi pregunta es causada por mi pobre conocimiento del idioma inglés.

EDITAR: Relacionado: ¿Por qué el tamaño máximo de una matriz es "demasiado grande"?


Creo que es un error de las palabras.

La regla en [expr.add] se hereda de la misma regla para la resta del puntero en el estándar C. En el estándar C, ptrdiff_t no necesita mantener ninguna diferencia de dos subíndices en un objeto de matriz.

La regla en [support.types.layout] proviene de Core Language Issue 1122 . Agregó definiciones directas para std::size_t y std::ptrdiff_t , que se supone que resuelve el problema de la definición circular. No veo que haya ninguna razón (al menos no mencionada en ningún documento oficial) para hacer que std::ptrdiff_t mantenga la diferencia de dos subíndices en un objeto de matriz. Supongo que solo usa una definición incorrecta para resolver el problema de definición circular.

Como otra evidencia, [diff.library] no menciona ninguna diferencia entre std::ptrdiff_t en C ++ y ptrdiff_t en C. Como en C ptrdiff_t no tiene tal restricción, en C ++ std::ptrdiff_t no debería tener esa restricción también.