Never been to TextSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

« Newer Snippets
Older Snippets »
7 total  XML / RSS feed 

Multiple __attributes__

Multiple __attributes__ can be strung together on a single declaration, and this is not uncommon in practice. You can either use two separate __attribute__s, or use one with a comma-separated list:

/* send printf-like message to stderr and exit */
extern void die(const char *format, ...)
        __attribute__((noreturn))
        __attribute__((format(printf, 1, 2)));

/*or*/

extern void die(const char *format, ...)
        __attribute__((noreturn, format(printf, 1, 2)));

__attribute__ const

This attribute marks the function as considering only its numeric parameters. This is mainly intended for the compiler to optimize away repeated calls to a function that the compiler knows will return the same value repeatedly. It applies mostly to math functions that have no static state or side effects, and whose return is solely determined by the inputs.

In this highly-contrived example, the compiler normally must call the square() function in every loop even though we know that it's going to return the same value each time:

extern int square(int n) __attribute__((const));

...
        for (i = 0; i < 100; i++ )
        {
                total += square(5) + i;
        }


By adding __attribute__((const)), the compiler can choose to call the function just once and cache the return value.

__attribute__ noreturn

This attribute tells the compiler that the function won't ever return, and this can be used to suppress errors about code paths not being reached. The C library functions abort() and exit() are both declared with this attribute:

extern void exit(int) __attribute__((noreturn));
extern void abort(void) __attribute__((noreturn));

$ cat test2.c
extern void exitnow() __attribute__((noreturn));

int foo(int n)
{
        if ( n > 0 )
                exitnow();
        else
                return 0;
}

$ cc -c -Wall test2.c
no warnings!

__attribute__ format

This __attribute__ allows assigning printf-like or scanf-like characteristics to the declared function, and this enables the compiler to check the format string against the parameters provided throughout the code. This is exceptionally helpful in tracking down hard-to-find bugs.

There are two flavors:

* __attribute__((format(printf,m,n)))
* __attribute__((format(scanf,m,n)))

but in practice we use the first one much more often.

The (m) is the number of the "format string" parameter, and (n) is the number of the first variadic parameter.


/* like printf() but to standard error only */
extern void eprintf(const char *format, ...)
        __attribute__((format(printf, 1, 2)));  /* 1=format 2=params */

/* printf only if debugging is at the desired level */
extern void dprintf(int dlevel, const char *format, ...)
        __attribute__((format(printf, 2, 3)));  /* 2=format 3=params */

$ cat test.c
1  extern void eprintf(const char *format, ...)
2               __attribute__((format(printf, 1, 2)));
3
4  void foo()
5  {
6      eprintf("s=%s\n", 5);             /* error on this line */
7
8      eprintf("n=%d,%d,%d\n", 1, 2);    /* error on this line */
9  }

$ cc -Wall -c test.c
test.c: In function `foo':
test.c:6: warning: format argument is not a pointer (arg 2)
test.c:8: warning: too few arguments for format

Processing a Native Window Message Inside a Non-visual Class

Say you have a dynamic library and you want to treat a native window message inside any non-visual class in that library.
Derive this class from NativeWindow as shown below. After creating the new class from Class1, you can pass the Handle (like IntPtr) of this class to any native function.

public class Class1: NativeWindow
{
        CreateParams cp = new CreateParams();

        public Class1()
        {
                // Create the actual window
                this.CreateHandle(cp);
        }

        protected override void WndProc(ref Message m)
        {
                if(m.Msg == WM_...)
                {
                        // Do something here in response to messages
                        return;
                }
                base.WndProc(ref m);
        }

}

C macro that implements count_if, sum, max_elem

// C macro that does count_if, sum, max_elem.

#define COUNT_IF(ITERATION, CONDITION, COUNT)  {COUNT =0; ITERATION {if(CONDITION) COUNT++;}}  
/* ex: COUNT_IF( for(i=0;i++;i<10), i%2==0, evens)  [counting the number of evens.]  */

#define SUM(ITERATION, EXPRESSION, SUMM)  {SUMM =0; ITERATION {SUMM +=(EXPRESSION);}}  
/* if ITERATION is an empty iteration, the sum is 0
SUM( for(i=0;i<60;i++) if(zik[i]==sol[i]) , score[i], actual_score ) */


#define MAX_ELEM(ITERATION, EXPRESSION, MAX_VALUE, POSITION)  { \
        bool first233496 = true;                                   \
        ITERATION {                                               \
                if(first233496){ first233496 = false; POSITION ; MAX_VALUE =(EXPRESSION); } \
                else if((EXPRESSION)> MAX_VALUE ){ POSITION ; MAX_VALUE =(EXPRESSION); }   \
        }                                               \
}
/* if ITERATION is an empty iteration, this macro does not work.
ex: MAX_ELEM(for(x=0;x<5;x++) for(y=0;y<5;y++) , x-2*y , maximum , {m_x=x;m_y=y;} );  [ Set (m_x,m_y,maximum) := (x,y,x-2*y) when x-2*y achieves maximum value] 
ex: MAX_ELEM( ON(i,10), (10-v[i])*v[i], d, k=i); */

Convenient and fast text input using a numeric keypad

Recently, I had to program a device that had only a numeric keypad for some light data entry. The manufacturer had a relatively cumbersome method for entering text and I had to come up with an alternative means to more conveniently enter text using the numeric keypad.

The application did not require mixed case characters, so I decided to limit data entry to uppercase characters to reduce the number of keystrokes required. Unlike typical mobile phone input, there is no timeout for the next character to be entered. Adding this is not hard at all, and would probably only require about three to five extra lines of code ...

void succ(int* ip, char* cp, char* ch)
{
    int il = strlen(ch);
    char *np;
        
    if(*(cp + *ip) == '\0') {
        *(cp + *ip) = *ch;
        return;
    }
        
    np = strchr(ch, *(cp + *ip));
        
    if(np == NULL) {
        (*ip)++;
        *(cp + *ip) = *ch;
    } else if(np == ch + il - 1) {
        *(cp + *ip) = *ch;
    } else {
        *(cp + *ip) = *(np + 1);
    }
}

int textual_input(int line, char *destination, int maxlen)
{
    int nKey, i = 0;
    char text[128];

    memset(text, 0, sizeof(text));

    while(1)
    {
        nKey = Sys_Key_WaitKey();
        switch (nKey)
        {
            case KEY_DEL: text[i] = '\0'; i > 0 ? i-- : i = 0; break;
            case KEY_0: i++; text[i] = ' '; break;
            case KEY_1: i++; break;
            case KEY_2: succ(&i, text, "ABC"); break;
            case KEY_3: succ(&i, text, "DEF"); break;
            case KEY_4: succ(&i, text, "GHI"); break;
            case KEY_5: succ(&i, text, "JKL"); break;
            case KEY_6: succ(&i, text, "MNO"); break;
            case KEY_7: succ(&i, text, "PQRS"); break;
            case KEY_8: succ(&i, text, "TUV"); break;
            case KEY_9: succ(&i, text, "WXYZ"); break;
            case KEY_ENTER: goto done; break;
            case KEY_CANCEL: goto cancel; break;
        }
        Syd_ClearWindow(line,line);
        Syd_DisplayLine(line, text, 0, ALIGN_LEFT );
    }
done:
    strncpy(destination, text, maxlen);
    return 0;
cancel:
    memset(destination, 0, maxlen);
    return -1;
}


I hope someone finds this code useful. It's not a huge piece of code, not hard to understand and is also small enough to maintain. As always, I love to hear of better ways to do things so any suggestions are welcome!
« Newer Snippets
Older Snippets »
7 total  XML / RSS feed