Маленькая задачка на C

Dec 24, 2016 11:53

В коментариях родилась задачка, которая на мой взгляд, вполне заслуживает оформления отдельным постом:

Есть код на языке C

#include
#include

void something_wrong() {
  //(1)
  char * p;
  strcpy(p, "Hello");
  printf("%s World\n", p);
}
void some_other_code() {
}

int main()
{
  some_other_code();
  something_wrong();
  return 0;
}И ( Read more... )

prog, загадки

Leave a comment

Comments 7

e1am0 December 24 2016, 09:26:02 UTC
интересно, а оно там не затрёт чёнить важное?
ну второй вопрос -- правильные ответы будут?

Reply

filonov December 24 2016, 09:37:58 UTC
1) при правильном подходе - не затрет. Код получается заведомо корректный. Правда для варианта на 5 баллов, есть сложности с его получением.
2) со временем :)

Reply


hind19 December 24 2016, 13:20:14 UTC
С моими крайне скромными познаниями, вышло примерно так:
void something_wrong()
{
сhar x[6];
char * p = x;
strcpy(p, "Hello");
printf("%s World\n", p);
}
Исключая истерику компилятора по поводу strcpy, и то, что длина массива х подогнана руками, вроде как работает.
На "5" не претендую :) На "4" тоже.

Reply

filonov December 24 2016, 17:45:46 UTC

Не пойдёт, надо было только добавить строку,  а вы к определению p добавили его  инициализацию

Reply


absurdated December 24 2016, 20:43:08 UTC
На 4 балла:
Вариант А, две строки

char arr[6];
#define p p=arr

Вариант Б, одна строка (не уверен что по стандарту компилятор обязан это пропустить):

#define p p=(__LINE__ == 5 ? (char*)malloc(6) : p)

Вариант В, одна строка:

char p[6]; //\

Вариант Г, сомнительный в смысле корректности, одна строка:

char arr[6]; char* q; (&q)[1] = arr;

На 5 баллов: если среда исполнения обещает не вклиниваться между вызовами, а компилятор выделяет память для локальных переменных идентичным образом, то может быть достаточно
void some_other_code() { static char arr[6]; char* p = arr; }
...но, по-моему, это нереальные требования, а как их ослабить - непонятно.

Reply

filonov December 24 2016, 22:14:16 UTC
Вариант Г заведомо некорректный. Направление стека платформозависимо.
Б не пропускает компилятор, хотя он, как ни странно, наиболее близок к решению, которое мне кажется наиболее надежным. Но вы пошли не тем путем.
Вариант В интересен - но полностью убирает неинициализированный указатель, что скучно.
Ну и все варианты ломаются если мы не знаем длины копируемой строки.

Код на 5 баллов - верный. Требования как раз вполне реальные. gcc не пытается быть умнее человека и ведет себя так по дефолту, как впрочем и большинство компиляторов, поскольку порядок передачи параметров и работа со стеком для С стандартизованы.
Сделать это на MSVC в Debug невозможно совсем, поскольку он неявно инициализирует все указатели. В Release может и можно - но возиться с ключами компиляции мне лень - слишком неактуальная платформа.

Reply

filonov December 25 2016, 08:46:59 UTC
Я пока скрою ваш комментарий.

Reply


Leave a comment

Up