Si bien es cierto que el comportamiento está bien definido - es no cierto que los compiladores pueden "optimizar para la const" en el sentido de que usted se refiere.
Es decir, un compilador no puede asumir que solo porque un parámetro sea a const T* ptr, la memoria a la que apunta ptrno se cambiará a través de otro puntero. Los punteros ni siquiera tienen que ser iguales. El constes una obligación, no una garantía, una obligación suya (= la función) de no realizar cambios a través de ese puntero.
Para tener esa garantía, debe marcar el puntero con la restrictpalabra clave. Por lo tanto, si compila estas dos funciones:
int foo(const int* x, int* y) {
int result = *x;
(*y)++;
return result + *x;
}
int bar(const int* x, int* restrict y) {
int result = *x;
(*y)++;
return result + *x;
}
la foo()función debe leer dos veces x, mientras que bar()solo necesita leerla una vez:
foo:
mov eax, DWORD PTR [rdi]
add DWORD PTR [rsi], 1
add eax, DWORD PTR [rdi] # second read
ret
bar:
mov eax, DWORD PTR [rdi]
add DWORD PTR [rsi], 1
add eax, eax # no second read
ret
Mira esto en vivo GodBolt.
restrictes solo una palabra clave en C (desde C99); desafortunadamente, no se ha introducido en C ++ hasta ahora (por la mala razón de que es más complicado introducirlo en C ++). Sin embargo, muchos compiladores sí lo admiten __restrict.
En pocas palabras: el compilador debe admitir su caso de uso "esotérico" al compilar f(), y no tendrá ningún problema.
Vea esta publicación sobre casos de uso para restrict.
constno es "una obligación suya (= la función) no hacer cambios a través de ese puntero". El estándar C permite que la función se elimineconstmediante una conversión y luego se modifique el objeto a través del resultado. Esencialmente,constes solo una asesoría y una conveniencia para el programador para ayudar a evitar modificar un objeto sin darse cuenta.memcpyystrcpyse declaran conrestrictargumentos, mientrasmemmoveque no lo es: solo este último permite la superposición entre los bloques de memoria.Esto está bien definido (en C ++, ya no estoy seguro en C), con y sin el
constcalificador.Lo primero que debe buscar es la estricta regla de alias 1 . Si
srcydstapunta al mismo objeto:char*ychar const*no son compatibleschar*ychar const*son similaresCon respecto al
constcalificador, podría argumentar que, dado que cuandodst == srcsu función modifica efectivamente a quésrcpuntos,srcno debería calificarse comoconst. Así no es comoconstfunciona. Deben considerarse dos casos:const, como enchar const data[42];, modificarlo (directa o indirectamente) conduce a Comportamiento indefinido.constse define una referencia o puntero a un objeto, como enchar const* pdata = data;, se puede modificar el objeto subyacente siempre que no se haya definido comoconst2 (ver 1.). Entonces lo siguiente está bien definido:1) ¿Cuál es la estricta regla de alias?
2) ¿Es
const_castseguro?fuente
char*ychar const*no son compatibles_Generic((char *) 0, const char *: 1, default: 0))evalúa a cero.constse define una referencia o un puntero a un objeto" es incorrecta. Quiere decir que cuando se define una referencia o un puntero a un tipoconstcalificado , eso no significa que el objeto al que está configurado para apuntar no puede modificarse (por varios medios). (Si el puntero apunta a un objeto, eso significa que el objeto es por definición, por lo que el comportamiento de tratar de modificarlo no está definido.)constconstlanguage-lawyer. La exactitud es un valor que aprecio, pero también soy consciente de que viene con más complejidad. Aquí, decidí ir por simplicidad y oraciones fáciles de entender, porque creo que esto es lo que quería OP OP. Si piensa lo contrario, responda, estaré entre los primeros en votarlo. De todos modos, gracias por tu comentario.Esto está bien definido en C. Las reglas de alias estrictas no se aplican con el
chartipo, ni con dos punteros del mismo tipo.No estoy seguro de lo que quieres decir con "optimizar para
const". Mi compilador (GCC 8.3.0 x86-64) genera exactamente el mismo código para ambos casos. Si agrega elrestrictespecificador a los punteros, el código generado es ligeramente mejor, pero eso no funcionará para su caso, ya que los punteros son los mismos.(C11 §6.5 7)
En este caso (sin
restrict), siempre obtendrá121como resultado.fuente