اطلاعیه

Collapse
No announcement yet.

ترفندهای زبان C

Collapse
X
 
  • فیلتر
  • زمان
  • Show
Clear All
new posts

    ترفندهای زبان C

    مشغول چرخ زدن در وب بودم که بصورت کاملا اتفاقی به صفحهٔ جالبی با عنوان شوخی! در وبسایت پروژهٔ گنو رسیدم.
    http://www.gnu.org/fun/fun.html

    این صفحه حاوی جکهایی است که هکرها برای نرمآ‌افزارها ، مستندات ، موزیکها و ... میسازن که طی چندین سال جمعآ‌آوری شده !
    برام جالب شد و یکی یکی اونهارو خواندم تا رسیدم به جکی با عنوان !Hello World

    در این جک نوشتن برنامهٔ سنتی Hello World دستمایه قرار داده شده که افراد مختلف چطور این برنامه رو میآ‌نویسن.
    همونطور که میآ‌دونید و حتما هم نیاز به توضیح نیست! معمولا در آموزش زبانهای برنامهآ‌نویسی اولین برنامهآ‌ای که آموزش داده میشه ، این هست که جملهٔ Hello World در خروجی دستگاه (مثلا بر روی مانیتور) چاپ بشه و این تقریبا مثل یک قانون در اومده!


    حالا دیگه من زیاد از این جک نمیآ‌گم و خودتون برید در این صفحه بخونیدش :
    http://www.gnu.org/fun/jokes/helloworld.html

    شروع کردم به خوندن جک و رسیدم به اینکه یه مدیر سیستم (System Administrator) چطور یک برنامهٔ Hello World رو میآ‌نویسه.
    کد PHP:
    #include <stdio.h>
     #include <stdlib.h>
     
    main()
     {
     
    char *tmp;
     
    int i=0;
     
    /* on y va bourin */
     
    tmp=(char *)malloc(1024*sizeof(char));
     while (
    tmp[i]="Hello Wolrd"[i++]);
     
    /* Ooopps y'a une infusion ! */
     
    i=(int)tmp[8];
     
    tmp[8]=tmp[9];
     
    tmp[9]=(char)i;
     
    printf("%s\n",tmp);
     } 


    برنامه رو خوندم و از یک جاییش سر در نیاوردم! داخل حلقهٔ while چیزی نوشته شده بود که بنظرم خیلی غریب اومد.
    فکر کردم شاید جکه و برنامه همینجوری نوشته شده. برنامه رو در یک ادیتور متن کپی و ذخیره کردم و دستور gcc main.c را برای کامپایلش در خط فرمان نوشتم و در کمال تعجب کامپایلر خطایی نداد !
    فایل اجرایی تولید شده بنام a.out رو اجرا کردم و باز هم در کمال نا باوری کلمهٔ Hello World بر روی صفحهٔ مانیتورم نمایش داده شد!

    اینجا بود که یک جک تبدیل شد به آموزش یه ترفند عالی!
    و با خودم گفتم چقدر خوب میشه تعداد بیشتری از این ترفندهارو یاد بگیرم و برای لذت بخشتر شدن کارم تو برنامهآ‌هام استفاده کنم.

    این بود که این تاپیک رو زدم برای اینکه تجربیات و ترفندهای دوستان در استفاده از زبان C به اشتراک گذاشته بشه.
    البته بعد از کمی جستجو به سایتهایی با همین هدف رسیدم که سعی میآ‌کنم ترفندهای جالب و کاربردیآ‌ای رو که درشون میآ‌بینم ترجمه کنم و اینجا هم بنویسیم. (البته تجربه نشون داده اینطور تاپیکآ‌ها بعد از مدتی از کار میآ‌افتند )
    http://ctips.pbworks.com
    http://c-faq.com

    خب! اولین ترفند رو بگم که از همین جوک Hello world یاد گرفتم!
    چطوری با استفاده از حلقهٔ While یک متغیر رشتهٔ حرفی رو براحتی مقداردهی کنیم ؟
    کد PHP:
    #include <stdio.h>

    main(){
        
    char str[20];
        
    int i=0;
        
        while( 
    str[i] = "Sample text"[i++] );
        
        
    printf("%s\n", str);



    روش دیگر استفاه از تابع strcpy است.
    کد PHP:
    #include <stdio.h>
    #include <string.h>

    main(){
        
    char str[20];
        
        
    strcpy(str, "Sample text");
        
        
    printf("%s\n", str);



    ...
    چگونه هوشمندانه بپرسیم

    #2
    پاسخ : ترفندهای زبان C

    حمیدجان کاش میشد چندین بار از شما تشکرکنم(شاید چندتا یوزر ساختم و اینکارو کردم!)
    دوستانی که این تاپیک رو دیدن کم لطفی نکنن، هیچی که نداشته باشه حداقل تو خیلی از کارا باعث میشه از یه فانکشن و هدر کمتر استفاده کنیم حجم کد کم میشه و سرعت میره بالا...

    من هم اگه ترفندی دیدم یا به ذهنم رسید همینجا میگم

    مرسی جناب رستمی
    {خلاف قوانین - امضا ویرایش شد}

    دیدگاه


      #3
      پاسخ : ترفندهای زبان C

      تشخیص یکسان بودن دو متغیر رشتهٔ حرفی

      کد PHP:
      #include <string.h>

      if(!strcmp(s1s2)) // This is a BAD way to do it, it's counterintuitive because ! means not. 


      معنی کارکتر ! نات کردن است ، پس استفاده از آن در اینجا کار درستی نیست. چون خروجی تابع strcmp ممکن است -1 هم باشد.
      راه بهتر برای تشخیص یکسان بودن دو متغیر رشتهٔ حرفی به این صورت است :

      کد PHP:
      #define Strequ(s1, s2) (strcmp((s1), (s2)) == 0)

      if(Strequ(s1s2)) // This make a lot more sense as to what you're testing 


      برای داشتن انعطاف بیشتر در مقایسهٔ رشتهآ‌های حرفی میتوان از تعریف زیر استفاده کرد.
      در این define شما قادرید عملوند برای مقایسهٔ دو رشته حرفی را نیز تعیین کنید :
      کد PHP:
      #define StrRel(s1, op, s2) (strcmp((s1), (s2)) op 0)

      //Then call it with:

      StrRel(s1, ==, s2);

      StrRel(s1, !=, s2);

      StrRel(s1, <=, s2); 



      منبع :
      http://c-faq.com/style/strcmp.html
      چگونه هوشمندانه بپرسیم

      دیدگاه


        #4
        پاسخ : ترفندهای زبان C

        جسارتا نمیخوام سردتون کنم ولی این پست ها بیشتر بخاطر اینه که یه چند تا چیز رو با هم دارین اشتباه میکنین.
        اولا: سی یک زبان نسبتا سطح پایین است. یه دلیل مهم اینکه ساختار ها پیچیده داخلی نداره و دقیقا به خاطر همین هم هست که سیستم عامل هارو عمدتا با C مینویسن.
        دوم اینکه متن ثابت "Hello World" در زمان کامپایل به یک آرایه تعبیر میشه و استفاده از یک آرایه یعنی دسترسی به آدرس پایه اون.
        ثالثا: راجع به آقای رستمی باید عرض کنم وقتی از اپراتور ! در چک نتیجه تابع strcmp استفاده میشه دقیقا میرسونه که برنامه نویس میخواسته equality رو چک کنه نه چیز دیگه. چون strcmp یک مقایسه بایتی انجام میده و تا جایی ادامه میده که یک بایت در یک رشته با هم اندیس خودش در رشته دوم متفاوت باشه. در این حالت تفاوت ایندو بایت رو بصورت یک مقدار صحیح علامتدار برمیگردونه.
        اما خوب بابت ماکرو ها باید خسته نباشید گفت چون کد رو خوانا تر میکنه.
        اماد از طرف دیگه انجام این تیپ کارها برای کاهش حجم یا افزایش سرعت برنامه خیلی کار درستی نیست. اول بایستی برنامه کار کنه. قابل نگهداری و توسعه باشه. و خوانا باشه. بعد از تمام اینها اگر شد که برنامه کوچکتر بشه و سریعتر شاید بدک نباشه. اما نبایستی این مسئله به قیمت ناخواناتر شدن برنامه یا کاهش اون فاکتورهایی که عرض کردم تموم بشه.

        راستی اگه شما از این جور چیزا خوشتون میاد این سورس رو امتحان و تفسیر کنین تا ببینین چقدر از C میدونین (نه از بابت برنامه نوشتن و چهار تا if و else قطار کردن بلکه بابت اینکه بدونین توی دل کامپایلر چه خبره):


        #include <stdio.h>

        void main(void)
        {
        printf("Hello\n"
        (*printf)("Hello\n"
        (**printf)("Hello\n"
        (***printf)("Hello\n"
        (****printf)("Hello\n"
        }



        لطفا قبل از کامپایل کردن مشخص کنین که اصولا این برنامه کامپایل و اجرا میشه و در هر صورت چرا؟

        در آخر: احیانا اگر نوشته من بوی تندی میده مطلقا منظورم همچین چیزی نیست و عذر میخوام.

        دیدگاه


          #5
          پاسخ : ترفندهای زبان C

          نوشته اصلی توسط رضا آقازاده


          #include <stdio.h>

          void main(void)
          {
          printf("Hello\n"
          (*printf)("Hello\n"
          (**printf)("Hello\n"
          (***printf)("Hello\n"
          (****printf)("Hello\n"
          }





          سلام

          تحلیل این برنامه به چه شکله؟

          دیدگاه


            #6
            پاسخ : ترفندهای زبان C

            بسیار بسیار اندوهگین و متاثر می شوم از یادآوری اینکه زنده یاد رضا آقازاده امروز در بین ما حضور ندارند تا به سوال شما جواب بدهند. اما بجای ایشان این پاسخ را به شما می دهم که تمام خط های موجود در تابع main به یک نتیجه منجر می شوند. چرا که اشاره گر به یک تابع معادل نام همان تابع است.
            اوژن: به معنای افکننده و شکست دهنده است
            دانایی، توانایی است-Knowledge is POWER
            برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
            وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
            قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
            اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
            ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

            دیدگاه


              #7
              پاسخ : ترفندهای زبان C

              نوشته اصلی توسط طراح
              بسیار بسیار اندوهگین و متاثر می شوم از یادآوری اینکه زنده یاد رضا آقازاده امروز در بین ما حضور ندارند تا به سوال شما جواب بدهند. اما بجای ایشان این پاسخ را به شما می دهم که تمام خط های موجود در تابع main به یک نتیجه منجر می شوند. چرا که اشاره گر به یک تابع معادل نام همان تابع است.
              سلام

              چرا داخل پرانتز؟پرانتز چه معنی می دهد اینجا ؟

              تعداد ستاره ها هیچ فرقی ایجاد نمی کند؟

              دیدگاه


                #8
                پاسخ : ترفندهای زبان C

                در مورد توابع برای اینکه قرار دادن ستاره به معنای اشاره گر به تابع باشد، باید در کنار نام تابع داخل پرانتز قرار بگیرد.

                نوشته اصلی توسط alirf
                تعداد ستاره ها هیچ فرقی ایجاد نمی کند؟
                در این مورد به خصوص (اشاره گر به تابع) نتیجه یکسانی حاصل می شود.
                اوژن: به معنای افکننده و شکست دهنده است
                دانایی، توانایی است-Knowledge is POWER
                برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
                وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
                قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
                اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
                ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

                دیدگاه


                  #9
                  پاسخ : ترفندهای زبان C


                  کد PHP:
                  #define MAX_TASK 3

                  void (*tasks[MAX_TASK])(void);  /* pointers to tasks functions */

                  void task1(void) {...}
                  void task2(void) {...}
                  void task3(void) {...}

                  main() {
                   ...
                   
                  tasks[0]=task1;
                   
                  tasks[1]=task2;
                   
                  tasks[2]=task3;
                   ...

                  گذشت خصلت مردان است

                  دیدگاه


                    #10
                    پاسخ : ترفندهای زبان C


                    کد PHP:
                    #define ASM(...) asm volatile (__VA_ARGS__)
                    #__))define ATTR(...)  __attribute__((__VA_ARGS 
                    گذشت خصلت مردان است

                    دیدگاه


                      #11
                      پاسخ : ترفندهای زبان C

                      مقدار دهی چند رجیستر با یک ماکرو

                      کد PHP:
                      #define adc_set(cnt) ADCSRA=cnt; ADMUX=cnt>>8; SFIOR|=cnt>>16

                       
                      adc_set0<<0<<16); 
                      گذشت خصلت مردان است

                      دیدگاه

                      لطفا صبر کنید...
                      X