2009-05-07 18 views
21

Tengo un conocimiento general de restrict pero espero aclarar algunos puntos finos. Tengo una función que lee una cadena terminada en nulo de un buffer y escribe una versión URL codificada en otro buffer. La función tiene esta firma (actualmente sin restrict):Cuándo usar Restringir y cuándo no a

char const *StringUrlEncode(char const *unencoded, 
          char *encoded, 
          char *encodedEnd); 

unencoded es mi cadena de origen terminada en nulo. El búfer de destino está representado por encoded y encodedEnd, donde encoded apunta al primer char en la memoria intermedia y encodedEnd apunta a que el primer carácter después el tampón, es decir, la función escribirán char s hasta, pero sin incluir la ubicación señaló por encodedEnd - este es su par iterador básico begin/end si está familiarizado con las convenciones C++ STL.

Si añado restrict a esta función, en caso de que sólo se puede aplicar a los dos primeros parámetros:

char const *StringUrlEncode(char const *restrict unencoded, 
          char *restrict encoded, 
          char *encodedEnd); 

o hay algún beneficio que no estoy entendiendo añadiéndolo a los tres parámetros?

Veo que hacer los buffers de entrada y salida restrict ayuda al compilador a saber que no se superponen. Pero dado que el último parámetro, encodedEnd, solo se usa para marcar el final del buffer de salida, estoy pensando que restrict no sería de ninguna ayuda para el compilador aquí (aunque supongo que no estaría mal, aparte de agregar ruido innecesario a la declaración de la función).

Respuesta

12

Pruebe el artículo de Mike Acton here. Restringir es aterrador debido tanto a las implicaciones de rendimiento de no usarlo como a las consecuencias de su uso incorrecto.

En su caso, parece que podría aplicar de forma segura restringir a los tres punteros ya que ninguno alias en la misma área de memoria. Sin embargo, habrá poco o ningún beneficio de rendimiento al usarlo en el tercer puntero.

+1

He leído el artículo de Mike (dos veces) y es un buen comienzo, pero me ha dejado algunas preguntas :-) –

+1

El enlace proporcionado no es funcional. Google sugiere que hay una versión actualizada en http://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html (validated 2009-09-06) pero eso también está dando problemas. La versión almacenada en caché está disponible en Google. –

4

Creo que tienes razón en que no haría daño. Su puntero de bucle (llámalo p) igualará el final codificado al final del bucle. Pero no es necesario acceder a nada después del bucle (desde p o encodedEnd), por lo que no debería ser un problema. Tampoco creo que sirva de nada, ya que nunca se escribe ni se lee nada de Codified End, por lo que no hay nada que optimizar.

Pero estoy de acuerdo con que tener los primeros dos restrictivos realmente debería ayudar.

+0

Tenga en cuenta que desreferenciando encodedEnd es un comportamiento indefinido ya que el codificado también es restrictivo, por lo tanto, no importa en absoluto si el encodedEnd es restrictivo o no. – bdonlan

7

En este caso particular, no importa si codificado End es restrictivo o no; ha prometido al compilador que nadie alias sin codificar y codificados, por lo que las lecturas y escrituras no interferirán entre sí.

La verdadera razón por la que restringen es importante en este caso es que sin ella el compilador no puede saber que escribe a través codificado no afectará lee a través sin codificar.Por ejemplo, si

encoded == unencoded+1 

continuación, cada escritura a codificado afectaría cada lectura posterior de sin codificar, por lo que el compilador no puede programar la carga hasta que la escritura se ha completado. Restringir le promete al compilador que los dos punteros no afectan a la misma memoria, por lo que puede programar cargas lo suficientemente adelante como para evitar paradas en la tubería.

Cuestiones relacionadas