Сбой программы при попытке установить символ массива символов - PullRequest
1 голос
/ 15 февраля 2011

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

Для кода:

char sweat[] ="Sweater";
warenkorb = new WareImKorb(new Textil (205366,4.2,sweat,40),2,warenkorb);
sweat[0] = '\0';

Теперь, если я вместо этого сделаю это:

char* sweat ="Sweater";

программа работает нормально, пока я не попробую пот [0] = '\ 0'; Тогда он просто ломается.

Однако это работает: char cc [] = "Свитер"; char * sweat = cc;

Меня действительно беспокоит то, что я не понимаю, почему не работает версия 1. Надеюсь, вы, ребята, сможете мне помочь, иначе я сойду с ума, задаваясь вопросом об этом.

Ответы [ 5 ]

5 голосов
/ 15 февраля 2011

«Свитер» - это строковый литерал, который может находиться в постоянной памяти. Использование синтаксиса char [] копирует этот литерал в массив char, используя синтаксис char * (который действительно должен быть const char *), просто указывает на исходный строковый литерал.

3 голосов
/ 15 февраля 2011
char* sweat ="Sweater";
sweat[0] = '\0'

Здесь sweat указывает на ПОСТОЯННЫЕ данные.«Свитер» - это константные литеральные данные, находящиеся где-то в постоянной памяти, и sweat указывает на эти данные как таковые. Он не копирует его. Поэтому, когда вы делаете sweat[0]='\0', он пытается изменить первый символ данных CONSTANT.Отсюда и ошибка.Кстати, хороший компилятор должен выдавать предупреждение, если вы не пишете const в своем объявлении, как const char* sweater = "Sweater".Смотрите предупреждение здесь: http://www.ideone.com/P47vv

Но когда вы пишете char sweat[] = "Sweater", создается массив char, копирующий данные из данных CONSTANT, которые равны "Sweater";сам элемент этого массива является изменяемым!


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

#include<cstdio>
int main() {
        char* sweat  ="Sweater";        //notice the warning
        const char* another ="Sweater"; //no warning!
        std::printf("%p\n", sweat);     //print the address
        std::printf("%p\n", another);   //print the address
        return 0;
}

Вывод:

0x8048610
0x8048610

Значит, оба printfs печатают один и тот же адрес!

Смотрите здесь: http://www.ideone.com/VcyM6

2 голосов
/ 15 февраля 2011

ASCII искусство на помощь! Версия char sweat[] в памяти выглядит следующим образом:

       +---+---+---+---+---+---+---+---+
sweat: |'S'|'w'|'e'|'a'|'t'|'e'|'r'| 0 |   char[8]
       +---+---+---+---+---+---+---+---+

В то время как версия char* sweat выглядит следующим образом:

       +---+---+---+---+---+---+---+---+
       |'S'|'w'|'e'|'a'|'t'|'e'|'r'| 0 |   const char[8]
       +---+---+---+---+---+---+---+---+
         ^
         |
         |
       +-|-+
sweat: | | |   char*
       +---+

Верно, char* указывает на const char. Тот факт, что вы можете присвоить строковый литерал неконстантному символьному указателю, является неприятным святым в статической системе типов C ++. Проклинаю тебя, обратная совместимость!

0 голосов
/ 15 февраля 2011

C ++ не является управляемым языком.Избегайте создания указателей на массивы символов, которые не имеют надлежащего размера.Оба следующих примера являются лучшими решениями:

char* sweater = new char[10];
sweater[0] = '\0';
delete [] sweater;
sweater = NULL;

Или еще лучше:

std::string sweater = "";
0 голосов
/ 15 февраля 2011

В версии, которая не работает, вы не создаете никакой массив символов. Вы играете только с указателями.

Чтобы sweat[0] = '\0' был допустимым оператором, вам нужно sweat, чтобы быть действительным массивом символов.

Это делается только с char sweat[] = "XXXX"; или символом sweat[20];

...