LINUX.ORG.RU

Подлости языков программирования: приглашаю покритиковать и пополнить


0

2

По мере знакомства с различными языками программирования обязательно натыкаешься на разные подлости. Я их для коллекции записываю :-)

Пока коллекция не очень большая. Я решил занести её в Википедию:
http://ru.wikipedia.org/wiki/Ловушки_языков_программирования

Надеюсь, будет интересно не только мне :-). Приглашаю критиковать и дополнять.

Кстати, ещё на эту тему:
http://alenacpp.blogspot.com/2008/10/blog-post.html
http://www.ruscript.net/scripts/32/

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

> Кука, ты?

А что, у нас теперь только Кука имеет право артикулировать самоочевидные вещи?

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

Хм, емнип, netbeans нормально хавает такие конструкции, щас под рукой нету, но обязательно проверю!

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

Я имел в виду, что не надо включать -Werror при завышенном уровне предупреждений (сверх того, что я описал выше).

А я считаю, что его включать полезно, чтобы полностью избавиться ото всех предупреждений.

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

> А что, у нас теперь только Кука имеет право артикулировать самоочевидные вещи?

Ну, ты тоже можешь. А то тут всякие архимаги секретное оружие палят.

anonymous
()

Сейчас накопал на одном сайте один из подводных камней си:

int a = 0;

if (1)
{
   int a = 42;
}

prinf("%i\n", a);

Результат будет: 0.

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

> Сейчас накопал на одном сайте один из подводных камней си:

Это в голове у тебя камень. Книги надо читать, а не по всяких сайтикам бегать.

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

Честно, не знал, что можно объявлять локальные переменные с видимостью в пределах одного блока. Наверное потому такого кода никогда и не писал.

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

> Честно, не знал, что можно объявлять локальные переменные с видимостью в пределах одного блока. Наверное потому такого кода никогда и не писал.

Ох ты ж блин, как же ты так умудрился, а?

ky-san
()
Ответ на: комментарий от delete83
int a = 0;

if (1)
{
   int a = 42;
}

prinf("%i\n", a);

не это ДАР

подлость тут

some.h
#define a blabla
other.c

int a = 0;

if (1)
{
   int a = 42;
}

prinf("%i\n", a);

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

Си я учил в далеком 2001 году в институте. Может в этом дело? С тех пор прошло много-много времени за 1С.

delete83 ★★
()

Чувак, википедия - не твой личный бложег. Пшел вон!

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

один даже на Comeau C++ Online скомпилился оба в MSVC прекрасно собираются и потом что такого необычного в этих примерах в одном внутреннее имя скрывает внешнее в другом рекурсия

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

Второй пример вполне законный, со скрытием имени.
А вот первый не компилируется на нормальных, читай стандартных компиляторах. Нельзя вызывать main, нельзя брать ее адрес.

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

согласен что это может быть непереносимо для прикладного софта с другой стороны любой startup code всегда вызывает main или например загрузчик системный вообще работает без всяких crt как по другому напишеш startup code ? или напишеш ядро с загрузчиком ? некорректно как то говорить нельзя для системного языка он прекрасно работает и без crt и без main по крайней мере Си не должен страдать от таких запретов

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

Может, будем проверять, прежде чем фигню постить? Нельзя так,компилятор сильно и больно даст по рукам.

ЧЯДНТ?

vadim@host3:~/tmp$ cat > 123.c
int main()
{
    int main;
    foo(main);
}
vadim@host3:~/tmp$ gcc -c 123.c 
vadim@host3:~/tmp$ cat > 123.c
int main()
{
    main();
}
vadim@host3:~/tmp$ gcc -c 123.c 
vadim@host3:~/tmp$ 

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

> Нельзя вызывать main, нельзя брать ее адрес.

Вот же оно как на самом деле, я и не знал. Что ж я без таких, как ты, делал. Умер бы от скуки, наверное.

ky-san
()
Ответ на: комментарий от Vamp

А вот первый не компилируется на нормальных, читай стандартных компиляторах.

Номер параграфа из стандарта языка назовешь?

Нельзя вызывать main, нельзя брать ее адрес.

Ты забыл добавить, что инициализирующий код libc на всех «нормальных» платформах работает при помощи астрала.

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

Ерунда это.

Вот (и не забываем про оптимизацию, -O2/-O3):

[code=c] #include <stdio.h> #include <stdlib.h> #include <stdint.h>

static uint32_t swap_words( uint32_t x ) { uint16_t* const px = (uint16_t*)&x; uint16_t hi = px[0]; uint16_t lo = px[1];

px[1] = hi; px[0] = lo;

return x; }

int main() { uint32_t x = 0x12345678; uint32_t y = swap_words(x);

if( x == y ) { fprintf(stderr, «You've just killed a kitten. The blood is on your hands.\n»); abort(); }

return 0; }

[/code]

ky-san
()
Ответ на: комментарий от ky-san
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>


static uint32_t
swap_words( uint32_t x )
{
    uint16_t* const px = (uint16_t*)&x;
    uint16_t        hi = px[0];
    uint16_t        lo = px[1];

    px[1] = hi;
    px[0] = lo;

    return x;
}


int
main()
{
    uint32_t x = 0x12345678;
    uint32_t y = swap_words(x);

    if( x == y ) {
        fprintf(stderr, "You've just killed a kitten. The blood is on your hands.\n");
        abort();
    }

    return 0;
}

ky-san
()
Ответ на: комментарий от aho

С -Wall собирать нечестно! ж)

На пример без ворнингов мне лень напрягать голову. Да и компиляторы уже довольно умные пошли, а сложные примеры будут хуже восприниматься.

ky-san
()
Ответ на: комментарий от aho

> компилятор захлебывается варнингами :)

Не вижу ворнингов.

geekless ★★
()
Ответ на: комментарий от aho
vadim@host3:~/tmp$ cat 123.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>


static uint32_t
swap_words( uint32_t x )
{
    uint16_t* const px = (uint16_t*)&x;
    uint16_t        hi = px[0];
    uint16_t        lo = px[1];

    px[1] = hi;
    px[0] = lo;

    return x;
}


int
main()
{
    uint32_t x = 0x12345678;
    uint32_t y = swap_words(x);

    if( x == y ) {
        fprintf(stderr, "You've just killed a kitten. The blood is on your hands.\n");
        abort();
    }

    return 0;
}

vadim@host3:~/tmp$ gcc -Wall -Wextra 123.c
vadim@host3:~/tmp$ 
geekless ★★
()
Ответ на: комментарий от ky-san
vadim@host3:~/tmp$ gcc -Wall -Wextra -O2 123.c
vadim@host3:~/tmp$ gcc -Wall -Wextra -O3 123.c
vadim@host3:~/tmp$ gcc -Wall -Wextra -Os 123.c
vadim@host3:~/tmp$ 

Мне подсунули пиратский gcc?

geekless ★★
()
Ответ на: комментарий от ky-san
vadim@host3:~/tmp$ gcc -Wall -Wextra -O3 123.c && ./a.out && echo 0
0
vadim@host3:~/tmp$ gcc --version
gcc (GCC) 4.5.2 20110127 (prerelease)
Copyright (C) 2010 Free Software Foundation, Inc.
Это свободно распространяемое программное обеспечение. Условия копирования
приведены в исходных текстах. Без гарантии каких-либо качеств, включая 
коммерческую ценность и применимость для каких-либо целей.
geekless ★★
()

В C++ STL контейнер vector имеет методы begin() и end().

Ну тогда до кучи индекс массива в Си и Перле, максимальное значение которого неожиданно(?) меньше размера массива. Уныленько получается.

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

Когда ты впервые пишешь что-то сложнее хеловорлда, это не так уж и очевидно.

В поезде молодой человек читает книгу и постоянно восклицает:
- Ничего себе!.. Вот это да... Не может быть!.. Ну и ну...
Соседка не выдерживает и спрашивает его:
- Да что вы там такое читаете?
- Орфографический словарь.

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

> Добавь в C# еще - если подключиться к эвенту 1 раз, а потом 2 раза отключиться, то на следующее подключение события все-равно не будет.

То есть если отключиться два раза, а потом два раза подключиться, то все ОК? Погляди что генерирует C# компилятор для события каким-нибудь IL дизассемблером. По крайней мере офтопиковый компилятор генерирует метод отключения/подключения, которые себя так не ведут.

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

Причем тут инициализующий код libc? Это что, часть твоей программы? А номер параграфа стандарта - это пожалуйста.
3.6.1, Main function

Пункт 3:
The function main shall not be used (3.2) within a program.

3.2 оставляю тебе для самостоятельного изучения.

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

Ты используешь компилятор С, а не С++.

Шлангом прикидываешься? В каком это месте речь шла про кресты? Во всей этой ветке комментов, начиная от Подлости языков программирования: приглашаю покритиковать и пополнить (комментарий) , говорится только о Си.

Причем тут инициализующий код libc? Это что, часть твоей программы?

При том, что он а) на самом Си и написан, и б) линкуется с программой точно так же, как любой другой скомпилированный .c -> .o файл, т.е. не является чем-то внешним по отношению к собираемой программе.

А номер параграфа стандарта - это пожалуйста. 3.6.1, Main function

ISO/IEC 9899:

3.6
1 byte
 addressable unit of data storage large enough to hold any member of the basic character
set of the execution environment
2 NOTE 1 It is possible to express the address of each individual byte of an object uniquely.
3 
NOTE 2 A byte is composed of a contiguous sequence of bits, the number of which is implementation-
defined. The least significant bit is called the low-order bit; the most significant bit is called the high-order
bit.

Поздравляю вас с соврамши.

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

А вот я с самого начала думал о C++. Так что кто шлангом прикидывается - это еще вопрос.
Ну я предлагаю особо не воевать и придти к общему мнению, что язык программирования в примерах надо указывать.
В С main звать можно, в C++ - нельзя.
Лады?

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

> А вот я с самого начала думал о C++.

Все телепаты заняты предсказанием БП в Японии, на ЛОРе ни одного не осталось.

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

>Все телепаты заняты предсказанием БП в Японии, на ЛОРе ни одного не осталось.

Так они же на ЛОРе и предсказывают, не?

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

вот если покапатся по стандартам можно найти тьму отличий между Си и Си++ а в книжках приводят несколько и мало того еще говорят что это подмножество вот так программист на Си не может быть уверен что он знает семантику привила законы процедурного подмножества языка С++ они даже на этом низком уровне различаются в дохрена где мест особенно если смотреть стандарты

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

> Может, книжку бы прочел... а то так и помрешь неграмотным.

Полистал драфт С99. Такого бреда не нашёл. Извиняй, но ты — балабол.

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