Интернирование строк...
От: Alximik509 Россия  
Дата: 30.03.10 15:17
Оценка: :))) :))) :)))
Всем добрый день.

Вопрос на сообразительность.
Что будет выведено после выполнения кода:

int main(int n, char *v)
{    
    char *p1 = "hello";
    char *p2 = "hello";
    p2[0] = '0';    
    if(p1 == p2)
        printf("equal\n");
    else
        printf("not equal\n");
    printf("%s", p1);
    return 0;
}


А теперь главный вопрос.
ПОЧЕМУ???
Re: писать внутрь строковых литералов -- а-та-та!
От: Erop Россия  
Дата: 30.03.10 15:19
Оценка: +4
Здравствуйте, Alximik509, Вы писали:

A>Всем добрый день.


A>Вопрос на сообразительность.

A>Что будет выведено после выполнения кода:

Скорее всего будет выведено "equal\n", а потом ещё пустая строка

A>А теперь главный вопрос.

A>ПОЧЕМУ???

Потому, что писать внутрь строковых литералов -- а-та-та!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Интернирование строк...
От: remark Россия http://www.1024cores.net/
Дата: 30.03.10 15:22
Оценка: +3 :)
Здравствуйте, Alximik509, Вы писали:

A>Вопрос на сообразительность.

A>Что будет выведено после выполнения кода:
A>А теперь главный вопрос.
A>ПОЧЕМУ???

UB+ID


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Интернирование строк...
От: pavel.yurchenko Украина  
Дата: 30.03.10 15:22
Оценка:
Здравствуйте, Alximik509, Вы писали:

A>Всем добрый день.


A>Вопрос на сообразительность.

A>Что будет выведено после выполнения кода:

A>
A>int main(int n, char *v)
A>{    
A>    char *p1 = "hello";
A>    char *p2 = "hello";
A>    p2[0] = '0';    
A>    if(p1 == p2)
A>        printf("equal\n");
A>    else
A>        printf("not equal\n");
A>    printf("%s", p1);
A>    return 0;
A>}
A>


A>А теперь главный вопрос.

A>ПОЧЕМУ???

Попробовал — падает на

p2[0] = '0';
Re: Интернирование строк...
От: MTimur  
Дата: 30.03.10 15:23
Оценка:
Здравствуйте, Alximik509, Вы писали:

A>Всем добрый день.


A>Вопрос на сообразительность.

A>Что будет выведено после выполнения кода:
A>А теперь главный вопрос.
A>ПОЧЕМУ???

p1 и p2 будут указывать на один кусок памяти?
А здесь не упадет?
A> p2[0] = '0';
Re: Интернирование строк...
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 30.03.10 15:25
Оценка:
Здравствуйте, Alximik509, Вы писали:
A>
A>    p2[0] = '0';    
A>


ub
Re: Интернирование строк...
От: achp  
Дата: 30.03.10 15:25
Оценка: :))) :))
Здравствуйте, Alximik509, Вы писали:

A>Что будет выведено после выполнения кода:


Программист выполнил недопустимую операцию и будет закрыт.
Re: Так и быть.
От: Erop Россия  
Дата: 30.03.10 15:26
Оценка: 1 (1)
Здравствуйте, Alximik509, Вы писали:

A>
A>    char *p1 = "hello";
A>    char *p2 = "hello";
A>


A>ПОЧЕМУ???

Ты, кстати, вроде бы забыл указать язык.
Когда ты пишешь
char *p1 = "hello";
то обычно происходит следующее.
1) Где-то в сегменте статических данных компилятор заводит место под 6 байт и кладёт туда твою строчку.
2) На мето оператора "char *p1 = "hello";" подставляет код инициализации переменной адресом этого места в сегменте статических данных.

Ну когда ты несколько строчек заводишь, большинство компиляторов пытаются сэкономить и если строчки совпадают начинают их переиспользовать. Так что когда ты напишешь
char *p2 = "hello";
компилятор нового места в сегменте статических данных не заведёт, а переиспользует старое.

Ну а дальше сам догадаешься, наверное.

Да, ещё момент. При записи в сегмент статических данных может повезти и память окажется доступна только для чтения. Словишь AV и сразу всё отладишь.
А может не повезти и память позволит в себя писать. Ну и будешь потом долго и занудно выяснять куда у тебя все "hello" в программе пропали

Удачи.

для спасибо тут есть кнопки.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Интернирование строк...
От: ДимДимыч Украина http://klug.org.ua
Дата: 30.03.10 15:40
Оценка: :)
Здравствуйте, Alximik509, Вы писали:

A>Что будет выведено после выполнения кода:


В правильной системе должно быть Segmentation Fault.

A>А теперь главный вопрос.

A>ПОЧЕМУ???

Потому что в .rodata секцию писать — ССЗБ.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re: Интернирование строк...
От: jazzer Россия Skype: enerjazzer
Дата: 30.03.10 15:51
Оценка:
Здравствуйте, Alximik509, Вы писали:

A>
A>    char *p2 = "hello";
A>    p2[0] = '0';    
A>


A>А теперь главный вопрос.

A>ПОЧЕМУ???

потому что UB — изменение константыа.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Так и быть.
От: Alximik509 Россия  
Дата: 30.03.10 16:37
Оценка:
Здравствуйте, Erop, Вы писали:

E>Когда ты пишешь
char *p1 = "hello";
то обычно происходит следующее.

E>1) Где-то в сегменте статических данных компилятор заводит место под 6 байт и кладёт туда твою строчку.
E>2) На мето оператора "char *p1 = "hello";" подставляет код инициализации переменной адресом этого места в сегменте статических данных.

E>Ну когда ты несколько строчек заводишь, большинство компиляторов пытаются сэкономить и если строчки совпадают начинают их переиспользовать. Так что когда ты напишешь
char *p2 = "hello";
компилятор нового места в сегменте статических данных не заведёт, а переиспользует старое.


E>Ну а дальше сам догадаешься, наверное.


Все верно! в этом то и фишка.
Конкретно: пробовал на VS2008 и gcc(ведут себя одинаково)
Они действительно объеденяют строки "hello" в одну, и соответственно сравнение указателей дает true во всех случаях.
А вот дальше интересней.
В дебаге:
прога честно падает на "access violatation error" ибо пытается обратиться к защищенной памяти. Все хорошо, все как и ожидалось.
В релизе:
а тут она прекрастно отрабатывает! ни одного варнинга от компилятора!(хоть бы поругался на меня зараза)
а выводит пот что:

equal
hello


Просмотр ассемблерного листинга показал, что компилятор тупо проигнорил присвоение, и при этом даже не заикнулся про это.
Re: Интернирование строк...
От: c-smile Канада http://terrainformatica.com
Дата: 30.03.10 16:40
Оценка:
Здравствуйте, Alximik509, Вы писали:

A>ПОЧЕМУ???


А что именно "ПОЧЕМУ???"

На всякий случай:

http://msdn.microsoft.com/en-us/library/s0s0asdt(VS.71).aspx
Re[3]: Так и быть.
От: Erop Россия  
Дата: 30.03.10 16:41
Оценка:
Здравствуйте, Alximik509, Вы писали:

A>Просмотр ассемблерного листинга показал, что компилятор тупо проигнорил присвоение, и при этом даже не заикнулся про это.


Ну дык имеет право. UB же...
Не предупредил, IMHO, зазря... Но утебя ворнинг может быть где-то в хедерах отключен
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Интернирование строк...
От: Alximik509 Россия  
Дата: 30.03.10 16:44
Оценка: :))
Здравствуйте, jazzer, Вы писали:

J>потому что UB — изменение константыа.


Заметьте какой тип у переменной. Как бы она не очень константа, да ей присваивается константа, но сама переменная ни ни.

Если писать так..
const char *p2 = "hello";

то нет вопросов, отвалится еще на компиляции.

Кстати, по этому поводу...
почему вот так нельзя
const char *p2 = "hello";
char *p1 = p2;


А вот так можно?
char *p2 = "hello";
Re[4]: Так и быть.
От: Alximik509 Россия  
Дата: 30.03.10 16:45
Оценка:
Здравствуйте, Erop, Вы писали:

E>Не предупредил, IMHO, зазря... Но утебя ворнинг может быть где-то в хедерах отключен


не.. специально выкрутил ворнинг на сколько можно
Re[3]: Так и быть.
От: remark Россия http://www.1024cores.net/
Дата: 30.03.10 17:06
Оценка: 2 (1) +1
Здравствуйте, Alximik509, Вы писали:

A>Все верно! в этом то и фишка.

A>Конкретно: пробовал на VS2008 и gcc(ведут себя одинаково)
A>Они действительно объеденяют строки "hello" в одну, и соответственно сравнение указателей дает true во всех случаях.

Выключи в студии опцию Enable String Polling (/GF)

A>А вот дальше интересней.

A>В дебаге:
A>прога честно падает на "access violatation error" ибо пытается обратиться к защищенной памяти. Все хорошо, все как и ожидалось.
A>В релизе:
A>а тут она прекрастно отрабатывает! ни одного варнинга от компилятора!(хоть бы поругался на меня зараза)

Конвертация строковых литералов из char const* в char* — это наследние С.

A>а выводит пот что:

A>
A>equal
A>hello
A>


A>Просмотр ассемблерного листинга показал, что компилятор тупо проигнорил присвоение, и при этом даже не заикнулся про это.


А о чём ему заикаться? Это не видимое поведение и переменную эту дальше по тексту ты не используешь.


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Интернирование строк...
От: jazzer Россия Skype: enerjazzer
Дата: 30.03.10 17:30
Оценка: 1 (1)
Здравствуйте, Alximik509, Вы писали:

A>Здравствуйте, jazzer, Вы писали:


J>>потому что UB — изменение константыа.


A>Заметьте какой тип у переменной. Как бы она не очень константа, да ей присваивается константа, но сама переменная ни ни.

константа в данном случае — это массив со строкой, а не указатель на него.

A>А вот так можно?

A>
A>char *p2 = "hello";
A>


Потому что для этого конкретного преобразования (литерал в неконстантный указатель) есть специальный пункт в стандарте.
Для совместимости с классическими функциями Си типа strlen.
Коего тут есть поклонники.

4.2/2

A string literal (2.13.4) that is not a wide string literal can be converted to an rvalue of type “pointer to char”; a wide string literal can be converted to an rvalue of type “pointer to wchar_t”. In either case, the result is a pointer to the first element of the array. This conversion is considered only when there is an explicit appropriate pointer target type, and not when there is a general need to convert from an lvalue to an rvalue. [Note: this conversion is deprecated. See Annex D. ] For the purpose of ranking in overload resolution (13.3.3.1.1), this conversion is considered an array-to-pointer conversion followed by a qualification conversion (4.4). [Example: "abc" is converted to “pointer to const char” as an array-to-pointer conversion, and then to “pointer to char” as a qualification conversion. ]


Ну и

D.4 Implicit conversion from const strings [depr.string]
1 The implicit conversion from const to non-const qualification for string literals (4.2) is deprecated.

jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Так и быть.
От: Erop Россия  
Дата: 30.03.10 17:43
Оценка:
Здравствуйте, Alximik509, Вы писали:

E>>Не предупредил, IMHO, зазря... Но утебя ворнинг может быть где-то в хедерах отключен

A>не.. специально выкрутил ворнинг на сколько можно

против отключения в хедерах это не помогает.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Интернирование строк...
От: Erop Россия  
Дата: 30.03.10 17:51
Оценка:
Здравствуйте, Alximik509, Вы писали:

A>Заметьте какой тип у переменной. Как бы она не очень константа, да ей присваивается константа, но сама переменная ни ни.


Ну ты таки про какой из двух языков-то спрашиваешь? Видимо про С++?..

A>А вот так можно?

A>
A>char *p2 = "hello";
A>


Для совместимости со старым сишным кодом. Это такое хитрое исключение из правил.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Так и быть.
От: skeptik_  
Дата: 30.03.10 21:35
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Alximik509, Вы писали:


E>>>Не предупредил, IMHO, зазря... Но утебя ворнинг может быть где-то в хедерах отключен

A>>не.. специально выкрутил ворнинг на сколько можно

E>против отключения в хедерах это не помогает.


Не, VC++ здесь молчит как партизан. Причём и 2010 тоже.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.