Если бы вы не навязывали странные и бесполезные ограничения на кодирование, вы сможете быстро увидеть проблемы с вашим кодом или даже вообще не создавать их. Проблема состоит в том, что следующее утверждение не имеет смысла - вы сравниваете char *
с char
, поскольку вы только раз ссылаетесь на str
один раз.
if ((*(str + i) + j) >= max)
Это то же самое, что написать
if ((str[i] + j) >= max)
, в котором вы можете увидеть очевидную ошибку, поскольку то, что вы пытаетесь написать, эквивалентно
if ((str[i][j]) >= max)
, которое будет
if (*(*(str + i) + j) >= max)
Ваш компилятор должен выдавать предупреждения, потому что сравнение между указателем и целым числом редко является чем-то, что вы хотели бы сделать.
Википедия имеет довольно всесторонний список методов оптимизации здесь.
Самый важный был бы переупорядочением доступа к памяти.
Отсутствующие заборы памяти или инструкции по сериализации, процессор свободен переупорядочить доступы памяти. Некоторые архитектуры процессора имеют ограничения на то, сколько они могут переупорядочить; Альфа известна тем, что она была самой слабой (т.е. тот, который может переупорядочить большинство).
Очень хорошая обработка предмета может быть найдена в исходной документации ядра Linux в Documentation/memory-barriers.txt.
Большую часть времени, лучше использовать примитивы блокировки из Вашего компилятора или стандартной библиотеки; они хорошо тестируются, должны иметь в распоряжении все необходимые барьеры памяти и вероятно вполне оптимизированы (оптимизирующий блокировку примитивов, хитро; даже эксперты могут иногда понимать их превратно).
Да, но каков точно Ваш вопрос?
Однако, так как это - интересная тема: приемы, что компиляторы и использование процессоров для оптимизации кода не должны взламывать код, даже с несколькими процессорами, в отсутствие условий состязания в том коде. Это называют гарантией последовательной непротиворечивости: если Ваша программа не будет иметь никаких условий состязания, и все данные правильно заблокированы то перед доступом будет вести себя код, как будто это выполнялось последовательно.
Существует действительно хорошее видео Herb Sutter, говорящего об этом здесь:
http://video.google.com/videoplay?docid=-4714369049736584770
Все должны наблюдать это :)
Ответ DavidK корректен, однако также очень важно знать о модели памяти для Вашего языка/времени выполнения. Даже без условий состязания и с последовательной непротиворечивостью и взаимоисключающим использованием Ваш код может все еще повредиться, когда данные кэшируются различными потоками, работающими в различных ядрах CPU. Некоторые языки, Java является одним примером, гарантируют состояние данных между потоками, когда взаимоисключающая блокировка используется, но это достаточно редко, чтобы просто гарантировать, что никакие два потока не могут получить доступ к данным одновременно. Необходимо использовать взаимное исключение корректным способом гарантировать, что время выполнения языка синхронизирует состояние данных между двумя потоками. В Java это сделано при наличии двух потоков, синхронизируются на том же объекте.
Вот хорошая страница, объясняя проблему и как она имела дело с в javas модели памяти.