Форум сайта python.su
857
ShamanЕсли не будешь знать язык, то будешь делать ошибки, даже полностью зная операционную систему и предметную область. Работать оно будет не так, как ты ожидаешь. Очень распространённая ошибка - вычисление размера указателя через sizeof вместо размера массива, прицепленного к этому указателю, - это от чего, от незнания операционной системы или предметной области? Нет же, просто человек не держит в голове семантику этой операции, поэтому ему кажется, что она сама там что-то сообразит. А многие не знают даже, что это именно операция одноместная, а не функция. В чём разница - функции можно передавать куда-то, тогда как операции передавать нельзя и они подчиняются правилам приоритета. Вообще, в C аппарат операций и их приоритетов очень мощный, за счёт этого код очень сильно сокращается, если сравнивать с аналогичным кодом на Паскале (Дельфи). А чтобы пользоваться этим мощным аппаратом, нужно знать стандарт. В общем, пиши на C практически; когда 100500 ошибок вылезет в самых неожиданных местах, когда ты посидишь в gdb несколько часов, чтобы понять хотя бы, в чём там дело, тогда ты и поймёшь силу стандарта. Как надоест запускать gdb всё время на каждый чих, так сразу стандарт и выучишь.
C С приходится знать не про язык, а про операционку и предметную область.
Отредактировано py.user.next (Май 3, 2017 08:59:10)
Офлайн
88
py.user.nextЭто детская ошибка, конечно же она от незнания языка и вызывает только умилительную улыбку. В том же C++ гораздо менее очевидных тонкостей на порядки больше.
Очень распространённая ошибка - вычисление размера указателя через sizeof вместо размера массива, прицепленного к этому указателю
Офлайн
857
ShamanТам многое надо в голове держать, такая ошибка получается не тогда, когда он сразу пишет, а тогда, когда он сначала на массиве делает, а потом, спустя какое-то время, решает заменить массив на указатель, а эту операцию забывает изменить следом. Поэтому нужно знать ещё все такие случаи, а это вырабатывается только со временем, когда понаступаешь на такие грабли. И только знание стандарта спасёт тебя от того, чтобы потом постоянно не сидеть в отладчике в своей же программе.
Это детская ошибка, конечно же она от незнания языка и вызывает только умилительную улыбку.
ShamanТам всё хуже, потому что сам язык хуже. То есть он должен был быть лучше, по идее, но получилось только хуже всё. Если брать аппарат операций, то в сишнике он понятный и простой и при этом мощный. В C++ же его стали менять и превратили в итоге в кашу-малашу - то есть ты его уже учить заманаешься, потому что он нелогичный какой-то. Или вот я всегда привожу в пример встроенные типы составные (список, очередь и подобные), ими никогда нельзя пользоваться сходу (как в питоне, например), их надо обязательно дописывать. В итоге, они как бы есть, но их как бы и нет. В питоне-то у тебя всё есть, в сишнике надо всё писать, а тут ни то ни сё. Да, и стандарт ты никогда весь не прочитаешь, потому что он большой, часто меняется, и там много лишнего, вообще в языке много лишнего. Сегодня что-то вводят, через год это же отменяют нафиг. Потом они ещё само ядро языка меняют, добавляя дубликаты конструкций. Вот поэтому сам питон классический на C сделан, а не на C++. В C меньше заморочек, учится он быстрее в несколько раз, и он не меняется каждый день.
В том же C++ гораздо менее очевидных тонкостей на порядки больше.
[guest@localhost ~]$ ll /bin/ls
-rwxr-xr-x. 1 root root 125372 авг 15 2013 /bin/ls
[guest@localhost ~]$ ll /bin/cat
-rwxr-xr-x. 1 root root 53316 авг 15 2013 /bin/cat
[guest@localhost ~]$ ll /bin/grep
-rwxr-xr-x. 1 root root 151120 окт 29 2013 /bin/grep
[guest@localhost ~]$ ll /bin/sed
-rwxr-xr-x. 1 root root 76384 авг 5 2013 /bin/sed
[guest@localhost ~]$ ll /bin/gawk
-rwxr-xr-x. 1 root root 556588 авг 4 2013 /bin/gawk
[guest@localhost ~]$
Отредактировано py.user.next (Май 3, 2017 11:24:23)
Офлайн
88
Мне D понравился, как практичный и минимально шокирующий привыкшего к ООП прога. Выраженных проблем с распуханием не имеет, миксуется с C/C++/Python и при необходимости собирается в динамически линкуемый бинарник.
Офлайн
857
ShamanНу, синтаксис я смотрел, для меня он всё равно что C++. Просто как C++ только с другим синтаксисом. Так что я его даже не рассматривал для изучения. C++ вот мне нужен для написания на Qt графического интерфейса. Было бы там на C возможно делать, я бы на C писал его. Всё равно, даже если на C++ пишу что-то, то это получается код на C только с дополнительными возможностями вроде классов, шаблонов для функий (чтобы произвольные типы принимала). Но питон в этом плане удобнее, у него как бы UX выше, чем у C++. На нём потому быстрее и пишешь, что в нём всё удобнее сделано. А в C++ долго нужно описывать, конструктор, деструктор, пространства имён обязательно проставлять (кстати, из-за них код удлинняется, больше букв становится, читать длиннющий код скучно). Не люблю читать цппшный код только потому, что там слишком много букв всегда. Какая-нибудь маленькая программка, а читаешь её целый час. Вот этого нет в C, потому что в коде только самое нужное записано.
Мне D понравился, как практичный и минимально шокирующий привыкшего к ООП прога.
Офлайн
88
py.user.nextТам семантика своя. Вот напишешь
Ну, синтаксис я смотрел, для меня он всё равно что C++. Просто как C++ только с другим синтаксисом.
int[3][4] arr;
arr[2][3] = 1;
Отредактировано Shaman (Май 4, 2017 09:30:11)
Офлайн
857
ShamanЧто-то почитал, вроде перепутал индексы ты, есть проверка границ, но обращение к элементам обычное.
Вот напишешьи обломаешься с выходом за границы массива.int[3][4] arr;
arr[2][3] = 1;
ShamanДелегаты в шарпе, но в шарпе указателей на функции нет. То есть в C аналог делегатов делается через указатели на функции.
Некоторые концепции ближе к шарпу
ShamanЮнит-тесты есть и в C, прекрасно работают и очень элементарные. Единственное что, я их перед компиляцией из исходников подредактировал, чтобы сплэшскрин убрать, который там по дефолту выпадает при каждом запуске тестов. А так там можно даже свиты делать.
юниттестов
#include <stdio.h>
#include <stdarg.h>
#include "CUnit/Basic.h"
#include "../cmdline.h"
void test_parse_argv_info(void);
void test_parse_argv_gender(void);
void test_parse_argv_words(void);
void test_progname_values(void);
void test_prog(void);
void test_opt(void);
int main(void)
{
CU_pSuite suite1, suite2;
suite1 = suite2 = NULL;
if (CU_initialize_registry() != CUE_SUCCESS)
return CU_get_error();
suite1 = CU_add_suite("suite for parse_argv", NULL, NULL);
if (suite1 == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
suite2 = CU_add_suite("suite for other", NULL, NULL);
if (suite2 == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (CU_add_test(suite1, "test info for parse_argv()",
test_parse_argv_info) == NULL
|| CU_add_test(suite1, "test gender for parse_argv()",
test_parse_argv_gender) == NULL
|| CU_add_test(suite1, "test words for parse_argv()",
test_parse_argv_words) == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (CU_add_test(suite2, "test values for progname()",
test_progname_values) == NULL
|| CU_add_test(suite2, "test values for prog",
test_prog) == NULL
|| CU_add_test(suite2, "test values for opt",
test_opt) == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();
}
char **make_argv(char *argv[], ...)
{
va_list args;
char **p = argv;
va_start(args, argv);
while ((*p++ = va_arg(args, char *)))
;
va_end(args);
return argv;
}
void test_parse_argv_info(void)
{
char *argv[10];
CU_ASSERT_FALSE(parse_argv(
1, make_argv(argv, "./prog", NULL)));
CU_ASSERT_FALSE(parse_argv(
2, make_argv(argv, "./prog", "--help", NULL)));
CU_ASSERT_FALSE(parse_argv(
2, make_argv(argv, "./prog", "--version", NULL)));
}
...
void test_progname_values(void)
{
char *progname(const char *);
CU_ASSERT_STRING_EQUAL(progname(""), "");
CU_ASSERT_STRING_EQUAL(progname("./"), "");
CU_ASSERT_STRING_EQUAL(progname("./prog"), "prog");
CU_ASSERT_STRING_EQUAL(progname("/dir/prog"), "prog");
CU_ASSERT_STRING_EQUAL(progname("/dir/dir/prog"), "prog");
CU_ASSERT_STRING_EQUAL(progname("./dir/prog"), "prog");
CU_ASSERT_STRING_EQUAL(progname("../dir/prog"), "prog");
CU_ASSERT_STRING_EQUAL(progname("../../dir/prog"), "prog");
CU_ASSERT_STRING_EQUAL(progname("../dir/../prog"), "prog");
CU_ASSERT_STRING_EQUAL(progname("..../prog"), "prog");
}
...
ShamanЕсть такое поверье, что в C невозможно ничего написать, так как в нём ничего нет, и нужно из-за этого переходить на C++, но на деле оказывается, что на нём можно всё написать. ООП там реализуется через функции + структуры. Пока этот принцип не поймёшь, конечно будет казаться, что всё сложно. Однако если мыслишь исполнителями (представляешь программу в виде дерева исполнителей, управляющих исполнителями), то там всё просто становится. Нечасто, конечно, такое можно встретить, часто читаю код, там этого, как правило, нет. Недавно читал код Ассанджа (который в посольстве сидит), он написал несколько прог в 90-х, и вот читаешь его и там такая каша, хотя можно было сделать красиво. Всё-таки, если каша, то большую прогу не напишешь, запутаешься, надо структурировать, налаживать связь между частями, а для этого технологию надо знать. Многие не знают, вот и говорят, что нереально что-то большое на C писать.
и ещё много всякого разного
Отредактировано py.user.next (Май 4, 2017 11:09:16)
Офлайн
88
py.user.nextПроверяем.
Что-то почитал, вроде перепутал индексы ты, есть проверка границ, но обращение к элементам обычное.
#include <stdio.h>
union {
int td[3][4];
int sd[12];
} tdata = {0};
int main()
{
tdata.td[1][0] = 1;
printf("%i , %i\n", tdata.sd[3], tdata.sd[4]);
return 0;
}
module main;
import std.stdio;
union TUnion {
int[3][4] td;
int[12] sd;
};
TUnion tdata;
int main()
{
tdata.td[1][0] = 1;
writefln("%s , %s", tdata.sd[3], tdata.sd[4]);
return 0;
}
union TUnion {
int td[4][3];
int sd[12];
};ldc2 -w -g -I/usr/import -c hello.d -of=obj/Debug/hello.o
hello.d(6): Warning: instead of C-style syntax, use D-style syntax 'int[3][4] td'
hello.d(7): Warning: instead of C-style syntax, use D-style syntax 'int[12] sd'
Отредактировано Shaman (Май 4, 2017 13:06:13)
Офлайн
857
ShamanТак он же пишет не про границы массива, а про синтаксис. Ты там написал про выход за границы массива, я стал искать и его не увидел. Про синтаксис-то понятно, он поддерживает оба синтаксиса, но старается пересадить на чисто свой (из-за того, что в новом синтаксисе тип становится яснее, так как всё в одном месте записано).
компилятор поругает:
Отредактировано py.user.next (Май 4, 2017 13:46:32)
Офлайн
88
py.user.nextТы невнимателен.
Так он же пишет не про границы массива, а про синтаксис. Ты там написал про выход за границы массива, я стал искать и его не увидел.
int td[4][3]
int[3][4] td
"4 массива типа int[3]".
module main;
int[3][4] td;
int main()
{
td[2][3] = 1;
return 0;
}
ldc2 -w -g -I/usr/import -c hello.d -of=obj/Debug/hello.o
hello.d(7): Error: array index 3 is out of bounds td[2][0 .. 3]
Офлайн