Связывание строковых литералов - PullRequest
1 голос
/ 13 августа 2011

Насколько мне известно, компоновщик пытается объединить два строковых литерала в один единственный литерал, если они оба одинаковы, например:

file1.c

char const* firstString = "foo";

file2.c

char const* secondString = "foo";

Результатом будет только один случай foo\0 в соответствующей секции памяти (сохранение 4 байта).Это особенно важно для встроенных приложений (как ведет себя avr-gcc против gcc).

Но мне было интересно, могу ли я действительно рассчитывать на это и полагаться, что если две строки равныКроме того, их указатели равны (при условии, что во всей программе вы передаете только строковые литералы, а строки, генерируемые во время выполнения, не существуют - что является разумным предположением в моем случае).Очевидно, что я хочу ускорить сравнение скорости с этим и позволить широко используемой функции получить строковый литерал, например, так:

void lock(char const*);
void unlock(char const*);

lock("test");
dosmth();
unlock("test");

По сути, я хочу избежать огромного перечисления и огромных переключателей внутриlock / unlock функции.

Ответы [ 4 ]

3 голосов
/ 13 августа 2011

На самом деле они не могут указывать на одну и ту же память, поскольку вы можете писать в них.

Теперь, если бы вы сказали:

char *s1 = "MyString";
char *s2 = "MyString";

тогда действительно возможно , что s1 == s2.Не думай, что это гарантировано.

2 голосов
/ 13 августа 2011

Я бы, вероятно, не рассчитывал на это, так как это зависит от компилятора от того, как символы разрешаются таким образом. Большинство компиляторов создают 1 экземпляр константной строки, а затем просто ссылаются на это, но я не буду зависеть от этого, так как есть случаи, когда это не работает. Лично я бы не использовал такие строки в вашем методе блокировки и разблокировки. Перечисление, вероятно, послужит вам лучше.

1 голос
/ 13 августа 2011

Я думаю, что вы на неправильном пути.Мало того, что компоновщик не объединяет строковые литералы из разных модулей компиляции, он, скорее всего, даже не создает для них внешний символ.

Даже внутри одного и того же модуля компиляции, компилятор может объединить два вхождения одного и того же строкового литерала в одно, но это не обязательно:

Не определено, различаются ли эти массивы при условии, что их элементы имеют соответствующие значения.

Теперь к реальной проблеме, которая, кажется, в источнике вашего вопроса.Выполнение пар блокировки / разблокировки на основе строковых литералов, вероятно, не очень хорошая идея для языка C. Как вы говорите, это имеет тенденцию увеличивать код с помощью switch или подобного.

Более естественным было бы иметьзаблокируйте тип и объявите глобальную переменную с различимым именем для каждого из ваших отличительных событий блокировки / разблокировки.Это вынуждает вас объявлять каждое такое событие так, чтобы оно было видно во всех ваших единицах компиляции, и выбирало одну единицу компиляции, где вы на самом деле ее определяете.

1 голос
/ 13 августа 2011

Компоновщик не должен ничего объединять. Он просто должен отобразить объявленный тип на определенный тип. Это включает в себя поиск определенного типа и заполнение смещений адресов для перехода к нужному элементу.

То, о чем вы говорите, будет оптимизирующим компоновщиком. Многие линкеры вообще не оптимизируют, а те, которые не выполняют оптимизационный стандарт, поэтому вы никогда не сможете обобщить за пределы наблюдаемых результатов для линкера, который вы обнаружите (на этом компьютере в то время).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...