2009-12-29 5 views
7

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

элементов в массиве:

#define ELEMENTS(x) (sizeof (x)/sizeof (*(x))) 

Odd array indexing:

a[5] = 5[a] 

Single line if/else/while/for safe #defines

#define FOO(X) do { f(X); g(X); } while (0) 
#define FOO(X) if (1) { f(X); g(X); } else 

Мой вопрос к специалисту Программисты там находится: Что идиомы, Практики, фрагменты кода, или малоизвестные факты много показывают код C, но могут быть не очень интуитивными, но предлагают хорошее понимание программирования на языке C?

+6

должно быть сообществом wiki –

+0

Жаль, что он был закрыт, бот не был вопросом ... –

ответ

11

«стрелка оператор» для подсчета вниз от п-1 до 0:

for (int i = n; i --> 0;) ... 

Это не очень часто, но это интересная иллюстрация, что в некотором смысле инициализации/тест/обновление частей for цикл являются условными. Это обычный шаблон, но вы все равно можете использовать любые произвольные выражения.

Это также приятное напоминание о том, как работает лексический анализ.

+0

http://cplusplus.co.il/2009/12/28/the-omnipotent-arrow-operator/ – rmn

+0

Существует просто не избежать этого могучего оператора. – GManNickG

+0

Хорошо подходит для линейного поиска. В конце концов, первое место, которое вы должны посмотреть, это последнее место, где вы что-то кладете. –

4

Оператор запятой, отлично документированный (K & R и т. Д.), Появляется в довольно большом алгоритмическом коде и часто является неожиданностью для многих программистов, которые раньше этого не встречали. Он часто используется, чтобы упростить некоторые конструкции петли:

#define kITERATIONS_MAX 10 
int i=0,j=0,array[kITERATIONS_MAX],outArray[kITERATIONS_MAX],temp=0; 

for (i=0,j=kITERATIONS_MAX-1; i < kITERATIONS_MAX; i++,j--) 
{ 
temp = array[i]*array[j]; 
outArray[i]=temp; 
} 

Приведенный выше код будет умножать элементы массива 0 до 9 с 9 через 0, избегая при этом вложенных циклов.

При использовании оператора запятой оцениваются как первое, так и второе выражения. Результат первого выражения игнорируется и возвращается результат второго выражения.

+0

Я использую оператор запятой в условиях «while», которые выполняют две вещи, обычно назначение, за которыми следует тест: 'while (c = getc(), c! = EOF) ...'. –

+0

@DavidRTribble 'c = getc()' оценивается как 'c', что означает, что вы могли бы просто (предположительно) использовать' while ((c = getc())! = EOF) ...' –

+0

@RobbieMckennie. Это правда, но мне легче читать две операции (назначение и сравнение) как два отдельных выражения в управляющем выражении' while'. –

5

Так как кто-то упомянет об этом в любом случае, это может быть и мне: Duff's Device. Это хорошая иллюстрация того, как ярлыки работают на C, и понимание этого дало мне «опыт аха» в первый раз. Это его исходный код:

send(to, from, count) 
register short *to, *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); 
    } 
} 

Сегодня один не будет использовать register и избежать определения функции старого стиля.

+0

Кроме того, как я понимаю, вы не хотите делать это на современном оптимизирующем компиляторе - вы просто будете мешать. – dubiousjim

Смежные вопросы