Как обращаться с заменой строковых литералов и почему важно выделять в куче? - PullRequest
1 голос
/ 15 мая 2019

Я слышал от кодера, что замена литералов c-строки вызывает неопределенное поведение.

например:.

char *a = "111";
a[0] = '2'; //Undefinded behaviour

Однако я не нахожу обходного пути, как в следующем упражнении, где мне нужно перевести 12-часовое время в военное время:

char* timeConversion(char* s) {
    char* military_time = malloc(9*sizeof(char));
    strncpy(military_time, s,8);
    if(s[8] == 'P'){
       if(s[0]!='1' || s[1]!='2'){
       char hours = 10*(s[0]-'0')+(s[1]-'0');
       hours += 12;
       char tenner = (hours/10) + '0';
       char onner = hours%10 + '0';
       military_time[0] = tenner; //undefined
       military_time[1] = onner;
       }
    } else {
        if(s[0]=='1' && s[1] =='2'){
            military_time[0] = '0';
            military_time[1]= '0';
        }
    }
    return military_time;
}

Есть ли способ обойти эту проблему?

Кроме того, меня интересует поведение этого кода. Замена:

char* military_time = malloc(9*sizeof(char));

с:

char* military_time = "12345678";

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

Спасибо.

1 Ответ

1 голос
/ 15 мая 2019

Я слышал от кодера, что замена литералов c-строки вызывает неопределенное поведение.

Правильно, вы не должны пытаться изменять строковые литералы.Они обычно помещаются компиляторами в область только для чтения.

Указатели на строковые литералы должны объявляться с const, чтобы избежать неопределенного поведения:

char const *a = "111"; 
a[0] = '2';            // Ok: compiler error, because assigment to const

Однако яне находите обходного пути, как в следующем упражнении, ...

char* military_time = malloc(9*sizeof(char)); не создает строковый литерал, поэтому military_time[0] = tenner; в порядке.

Вы можете изменить памятьдля которого вы выделили память для:

char b[] = "111";      // Create array and initialize with contents copied from literal
b[0] = '2';            // Ok: array can be modified

char *c = malloc(4);   // Create pointer which points to malloc'd area
strcpy(c, "111");      // Copy content from literal
c[0] = '2';            // Ok: pointer points to area that can be modified
char* military_time = "12345678";

вызывает неправильное поведение.

Да, код неверен по причинам, указанным выше.

...