LINUX.ORG.RU

Switch - помогите осилить в C

 , , вкурить,


0

4

Читаю книгу по C. Дошел до Switch. А тут в книге такой говянный пример приведен по работе с данным циклом, что просто пипец.

Лор, пожалуйста приведите простой пример использования switch.

P.S если правильно понял, то при введеном значении, это значение прогоняется по всему листу switch case: и как только оно совпадает, то происходит действие вложенное в case n:


Ответ на: комментарий от Eddy_Em

Кстати. Ни разу не пробовал: интересно, будет ли gcc ругаться, если в функцию, требующую аргументом type***, передать type**?

конечно будет. В крестах ещё и гемор с const добавляется.

drBatty ★★
()
Ответ на: комментарий от je-ke

Самый, пожалуй, огромный недостаток switch-case в C и других си-подобных языках это отсутствие условий.

для условий есть if/then.

drBatty ★★
()
Ответ на: комментарий от je-ke

Как же здесь хочется упомянуть хаскель, где такое поведение реализовано с помощью «сторожей».

Guards это примитивный сахар над if-then-else. Вот вложенный pattern matching, да, не вполне примитивное (требующее более сложной компиляции) построение над switch/case.

quasimoto ★★★★
()
Ответ на: комментарий от MKuznetsov

Не многого ли ты от людей хочешь?
Многие ли сейчас свяжут Зевса с Юпитером, и всомнят
«quod licet Jovi, non licet bovi»?

ABW ★★★★★
()
Ответ на: комментарий от drBatty

Коренным образом они не отличаются от массивов в других языках. И, кстати, не так уж и много языков, в которых есть статические массивы. А вот динамических массивов в С нет - нужно делать самому(или брать готовые откуда-то), через указатели.

и чем в С указатель на массив отличается от указателя на указатель?

Это разные типы, я же показывал.

int (*)[N] /* указатель на массив из N элементов типа int  */
int *         /* указатель на int - к нему может быть преобразован любой массив из int'ов  */
int **      /* указатель на указатель - говорит сам за себя */
Вас просто смущают неявные преобразования и отсутствие возможности передать массив по значению, что возможно почти для всех(но не всех - функции тоже передаются через указатель) других типов. А это в языке просто для удобства использования - массив все-равно не имеет смысла передавать по значению, а для функции это было бы совсем странно. В современных языках вообще почти все передается по ссылке. Как правило, передачу по значению или оставляют только для встроенных примитивных типов, или вообще убирают.

anonymous
()
Ответ на: комментарий от anonymous

Это разные типы, я же показывал.

типы разные, но разницы я не наблюдаю (кроме sizeof).

А это в языке просто для удобства использования - массив все-равно не имеет смысла передавать по значению, а для функции это было бы совсем странно.

почему это «не имеет»? было-бы удобно передавать char[4] как int. а функци - да, я знаю. С ней ничего нельзя делать, кроме как взять её адрес...

drBatty ★★
()
Ответ на: комментарий от drBatty

Так разница в типе и заключается. По большому счету указатель - это дженерик-тип - он имеет одно и тоже представление для разных фактических типов. Премущества только в контроле со стороны компилятора и в адресной арифметике(которая учитывает тип указателя). А так, что void *, что int*, что int (*)[N] - все имеют одно и тоже представление - адрес.

было-бы удобно передавать char[4] как int.

Так и представляй - сишечка же. Только для начала убедись, что int у тебя действительно 4 байта ;)

anonymous
()
Ответ на: комментарий от anonymous

А так, что void *, что int*, что int (*)[N] - все имеют одно и тоже представление - адрес.

ну наконец-то...

Так и представляй - сишечка же. Только для начала убедись, что int у тебя действительно 4 байта ;)

дык и представляю... куда деваться-то? структурами. Хотя часто по смыслу это таки никакая не структура, а именно массив.

drBatty ★★
()
Ответ на: комментарий от drBatty

Чего наконец-то? Ты не видешь смысла в различных типах для указателей? В различиях адресной арифметики? Типы разные и в этом суть.

anonymous
()
Ответ на: комментарий от LamerOk

Бггг. Забавно сообщать это персонажу с твоим ником. ;)

LamerOk ★★★★★
()
Ответ на: комментарий от hizel
void send(register* to, register* from, register count)
          // Псевдоустройство. Все комментарии сознательно удалены
          {
             register n=(count+7)/8;
             switch (count%8) {
                case 0:  do {  *to++ = *from++;
                case 7:        *to++ = *from++;
                case 6:        *to++ = *from++;
                case 5:        *to++ = *from++;
                case 4:        *to++ = *from++;
                case 3:        *to++ = *from++;
                case 2:        *to++ = *from++;
                case 1:        *to++ = *from++;
                             } while (--n>0);
            }
          }

Можете объяснить , зачем в приведенном коде нужен цикл? Результат выполнения одинаков что с ним, что без.

Zero010
()
Ответ на: комментарий от LamerOk

Ну это сути дела не меняет ;-)
Хотя через 21 прерывание очень удобно делать press any key

ms-dos32
()
Ответ на: комментарий от LamerOk

Неверно.

Верно, если собираетесь передавать в эту функцию буферы с количеством элементов от 0 до 8. Если собираетесь с 0 до 100, тогда, почему не написать 100 case`ов , что ограничиваться восьмью? Почему вообще вписали 8 -casе`oв? С книжки Страуструпа(там кстати немного другой код в этом упражнении)? Почему не 100,1000,100000 , раз так важна производительность. Вопрос насколько это эстетично, понятно и насколько оправданна такая оптимизация? Я провел следующий эксперимент:

1. Создал два файла

файл test1.c:

#include "stdio.h"
#include "stdlib.h"
#define reg int
void send(reg* to, reg* from, reg count)
{
reg n=(count+9)/10;
switch (count%10) {
 case 0: do {   *to++ = *from++;
 case 9:        *to++ = *from++;
 case 8:        *to++ = *from++;
 case 7:        *to++ = *from++;
 case 6:        *to++ = *from++;
 case 5:        *to++ = *from++;
 case 4:        *to++ = *from++;
 case 3:        *to++ = *from++;
 case 2:        *to++ = *from++;
 case 1:        *to++ = *from++;
       } while (--n>0);
 }
}

int main(int argc, char* argv[])
{
        reg *r1=(reg*)malloc(sizeof(reg)*10) ;
        reg *r2=(reg*)malloc(sizeof(reg)*10) ;
        int i,count=9995 ;
        for(i=0;i<10000;i++){
                r1[i]=i+30;
                r2[i]=50000-i;
         }
        send(r2, r1, count) ;
        return 0;
}

файл test2.c:

#include "stdio.h"
#include "stdlib.h"
#define reg int
void send(reg* to, reg* from, reg count)
{
  do {
        *to++ = *from++;
      } while (--count>0);
}




int main(int argc, char* argv[])
{
        reg *r1=(reg*)malloc(sizeof(reg)*10) ;
        reg *r2=(reg*)malloc(sizeof(reg)*10) ;
        int i,count=9995 ;
        for(i=0;i<10000;i++){
                r1[i]=i+30;
                r2[i]=50000-i;
            }
         send(r2, r1, count) ;
         return 0;
}

2. Откомпилировал их:

cc ./test1.c -o ./test1
cc ./test2.c -o ./test2

3. Запустил несколько раз с помощью time:


[@hstat daff]$ time ./test1

real    0m0.002s
user    0m0.000s
sys     0m0.002s
[@hstat daff]$ time ./test2

real    0m0.002s
user    0m0.000s
sys     0m0.001s
[@hstat daff]$ time ./test1

real    0m0.002s
user    0m0.000s
sys     0m0.002s
[@hstat daff]$ time ./test2

real    0m0.002s
user    0m0.000s
sys     0m0.002s
[@hstat daff]$ time ./test1

real    0m0.002s
user    0m0.001s
sys     0m0.001s
[@hstat daff]$ time ./test2

real    0m0.002s
user    0m0.001s
sys     0m0.001s
[@hstat daff]$ time ./test1

real    0m0.002s
user    0m0.001s
sys     0m0.001s
[@hstat daff]$ time ./test2

real    0m0.002s
user    0m0.001s
sys     0m0.001s


Откомпилировал их Выигрыш в производительности, если и есть, то очень незначительный. Есть большие сомнения, что такие фокусы стоит использовать.

Zero010
()
Ответ на: комментарий от Zero010

Только буферы имеело смысл побольше выделить, я начал с 10-ти элементов, потом забыл побольше памяти выделить, даже удивительно почему небыло переполнения буфера:



#include "stdio.h"
#include "stdlib.h"
#define reg int
void send(reg* to, reg* from, reg count)
{
reg n=(count+9)/10;
switch (count%10) {
 case 0: do {   *to++ = *from++;
 case 9:        *to++ = *from++;
 case 8:        *to++ = *from++;
 case 7:        *to++ = *from++;
 case 6:        *to++ = *from++;
 case 5:        *to++ = *from++;
 case 4:        *to++ = *from++;
 case 3:        *to++ = *from++;
 case 2:        *to++ = *from++;
 case 1:        *to++ = *from++;
       } while (--n>0);
 }
}




int main(int argc, char* argv[])
{
        reg *r1=(reg*)malloc(sizeof(reg)*10000) ;
        reg *r2=(reg*)malloc(sizeof(reg)*10000) ;
        int i,count=9995 ;
        for(i=0;i<10000;i++){
                r1[i]=i+30;
                r2[i]=50000-i;
              
        }
        
        send(r2, r1, count) ;
       
        return 0;
}
#include "stdio.h"
#include "stdlib.h"
#define reg int
void send(reg* to, reg* from, reg count)
{
  do {
        *to++ = *from++;
      } while (--count>0);
}




int main(int argc, char* argv[])
{
        reg *r1=(reg*)malloc(sizeof(reg)*10000) ;
        reg *r2=(reg*)malloc(sizeof(reg)*10000) ;
        int i,count=9995 ;
        for(i=0;i<10000;i++){
                r1[i]=i+30;
                r2[i]=50000-i;
 
        }
      
        send(r2, r1, count) ;
       

        return 0;
}

Но результат выполнения примерно тот же самый.

Zero010
()
Ответ на: комментарий от anonymous

Я мог бы написать получше, если бы не дурацкое условие делать все через switch

ms-dos32
()
Ответ на: комментарий от anonymous

man 2 send, дальше в говне разбираться не стал.

Причем тут это? Вы вообще смотрели о чем речь?( Речь об оптимазации пересылкой по даффу.) И зачем хамить, если ничего не поняли? Хамство - не аргумент!

Zero010
()
Ответ на: комментарий от anonymous

Все-таки насколько надо быть …., чтобы такое написать:

man 2 send, дальше в говне разбираться не стал.

Ну плохо знаешь С, ну не знаком с фундаментальными алгоритмами - ну ладно, но на вид, что общего имеет функция:

 ssize_t send(int sockfd, const void *buf, size_t len, int flags);  
с обсуждаемой функцией:
  void send(register* to, register* from, register count)
          // Псевдоустройство. Все комментарии сознательно удалены
          {
             register n=(count+7)/8;
             switch (count%8) {
                case 0:  do {  *to++ = *from++;
                case 7:        *to++ = *from++;
                case 6:        *to++ = *from++;
                case 5:        *to++ = *from++;
                case 4:        *to++ = *from++;
                case 3:        *to++ = *from++;
                case 2:        *to++ = *from++;
                case 1:        *to++ = *from++;
                             } while (--n>0);
            }
          }
из упражнения Страуструпа, которую привел hizel, как пример использования оператора switch? Просто чуть-чуть врубить мозг и не позориться можно?

А вообще вопрос об использовании такой оптимизации – интересный и дискуссионный, я все-таки думаю, так делать не стоит. Однако обсуждать это имеет смысл с нормальными людьми.

Zero010
()
Ответ на: комментарий от anonymous

Да, к слову, для тех кто не в теме, у Страуструп`а в («. Язык программирования C++.» в раздел 6.6 упр1.5) было так:

Что делается в следующем примере?

void send(int* to, int* from, int count)
          //Черный ящик. Полезные комментарии умышлено удалены
          {
             int n=(count+7)/8;
             switch (count%8) {
                case 0:  do {  *to++ = *from++;
                case 7:        *to++ = *from++;
                case 6:        *to++ = *from++;
                case 5:        *to++ = *from++;
                case 4:        *to++ = *from++;
                case 3:        *to++ = *from++;
                case 2:        *to++ = *from++;
                case 1:        *to++ = *from++;
                             } while (--n>0);
            }
          }
Зачем кому-нибудь может понадобиться подобный код?

Ответ, тем кто не понял:

Делается - пересылается count элементов из from в to Понадобиться - для уменьшения времени выполнения

Так-то школота, читайте книжки и меньше .... чего не понимаете .

Zero010
()
Ответ на: комментарий от Zero010

но на вид, что общего имеет функция

Название же, ну.

quasimoto ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.