язык C в Linux: вопросы начального уровня
Модератор: Olej
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
язык C в Linux: вопросы начального уровня
Мне выпала необходимость выполнить небольшой учебный курс для пары-тройки учеников, по использованию C в Linux... детали не важны .
И по ходу я придумываю не совсем тривиальные примеры, заставляющие детальнее подумать над синтаксическими правилами C ... хотя, казалось бы, чего там думать?
Но примеры получаются временами ... смешные. И я решил показывать их здесь. В расчёте на то, что кто-то, у кого есть любопытные примерчики, тоже покажет их здесь...
Кроме того, предлагаю всем, у кого возникнут вопросы и сомнения по C, писать о них тоже сюда - вместе разберёмся.
И по ходу я придумываю не совсем тривиальные примеры, заставляющие детальнее подумать над синтаксическими правилами C ... хотя, казалось бы, чего там думать?
Но примеры получаются временами ... смешные. И я решил показывать их здесь. В расчёте на то, что кто-то, у кого есть любопытные примерчики, тоже покажет их здесь...
Кроме того, предлагаю всем, у кого возникнут вопросы и сомнения по C, писать о них тоже сюда - вместе разберёмся.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: язык C в Linux: вопросы начального уровня
Типы данных (файл 1.c):Olej писал(а): Но примеры получаются временами ... смешные.
Код: Выделить всё
#include <stdio.h>
// скалярные типы данных:
int main () {
int i = 123;
short is = 12;
char ic1 = 3, ic2 = '2';
long il = 12345;
long long ill = 123456;
printf( " %d \n %d \n %d \n %d \n %lx \n %llx \n",
i, is, ic1, ic2, il, ill );
printf( "%c => %i\n", ic2, ic2 );
double rd = 3.14159265358979323846264338327950288419716939937510;
float rf = rd;
#define FMT "%30.27f"
printf( FMT" - "FMT" = "FMT"\n", rd, rf, rd - rf );
return 0;
}
Код: Выделить всё
bash-4.2$ ./exe1
123
12
3
50
3039
1e240
2 => 50
3.141592653589793115997963469 - 3.141592741012573242187500000 = -0.000000087422780126189536531
A = A;
A - A ... - это вовсе не равно 0
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: язык C в Linux: вопросы начального уровня
Следующая группа операций: агрегирование данных из простых скалярных (файл 2.c):Olej писал(а): Но примеры получаются временами ... смешные.
Код: Выделить всё
bash-4.2$ cat 2.c
#include <stdio.h>
#include <string.h>
#include <wchar.h>
// агрегаты данных:
int main () {
int ai[] = { 1, 2, 3, 4, 5 }, ni, j;
printf( "%d => ", ni = sizeof( ai ) / sizeof( ai[ 0 ] ) );
for( j = 0; j < ni; j++ ) printf( "%d, ", ai[ j ] );
printf( "\n" );
// разница в представлении
char ac[] = { '1', '2', '3', '4', '5', 0, '6', '\0' };
printf( "%d (строка %d) => ", ni = sizeof( ac ) / sizeof( ac[ 0 ] ), strlen( ac ) );
for( j = 0; j < ni; j++ ) printf( "%d, ", ac[ j ] );
printf( "\n" );
// присвоение структурных данных
struct ss {
int a1, a2, a3;
} vss1 = { 1, 2, 3 }, vss2 = { 3, 2, 1 };
vss1 = vss2;
printf( " %d %d %d \n", vss1.a1, vss1.a2, vss1.a3 );
// наложение разнородныз данных
struct su {
union {
char c[ 12 ];
short s[ 6 ];
float f[ 3 ];
};
} su1 = {{{ '1', '2', '3', '4', '5', '6', 0, 0, 0, 0, 0, 0 }}};
printf( "размер структуры %d байт\n", sizeof( su1 ) );
for( j = 0; j < sizeof( su1.c ) / sizeof( su1.c[ 0 ] ); j++ )
printf( "%d, ", su1.c[ j ] );
printf( "\n" );
for( j = 0; j < sizeof( su1.s ) / sizeof( su1.s[ 0 ] ); j++ )
printf( "%d, ", su1.s[ j ] );
printf( "\n" );
for( j = 0; j < sizeof( su1.f ) / sizeof( su1.f[ 0 ] ); j++ )
printf( "%f, ", su1.f[ j ] );
printf( "\n" );
char *p = (char*)&su1;
printf( "адрес=%p : %s, длина %d символов\n", p, p, strlen( p ) );
// разница длины UTF-8 строки (русскоязычной) в байтах и символах
const char buf[] = "русскоязычная строка";
printf( "строка: '%s', длина %d ,байт\n", buf, strlen( buf ) );
return 0;
}
Код: Выделить всё
bash-4.2$ ./exe2
5 => 1, 2, 3, 4, 5,
8 (строка 5) => 49, 50, 51, 52, 53, 0, 54, 0,
3 2 1
размер структуры 12 байт
49, 50, 51, 52, 53, 54, 0, 0, 0, 0, 0, 0,
12849, 13363, 13877, 0, 0, 0,
0.000000, 0.000000, 0.000000,
адрес=0xbf8c7e34 : 123456, длина 6 символов
строка: 'русскоязычная строка', длина 39 ,байт
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: язык C в Linux: вопросы начального уровня
Структуры управления (файл 3.c):
Здесь меньше веселья ... но всё же:
Код: Выделить всё
bash-4.2$ cat 3.c
#include <stdio.h>
// структуры управления:
int main () {
short s1[] = { 1, 2, 3, 4, 5, 6 },
ns = sizeof( s1 ) / sizeof( s1[ 0 ] ),
i;
for( i = 0; i < ns; i++ )
printf( "%d, ", s1[ i ] );
printf( "\n" );
i = -1;
while( ++i < ns ) {
printf( "%d, ", s1[ i ] );
}
printf( "\n" );
i = 0;
do {
printf( "%d, ", s1[ i ] );
} while( i++ < ns - 1 ); // !!!
printf( "\n" );
for( i = 0; i < ns; i++ ) {
printf( "%d : ", s1[ i ] );
switch( s1[ i ] ) {
case 1:
case 2:
printf( "%s ", "мало" );
break;
case 3:
printf( "%s ", "нормально" );
break;
case 4:
printf( "%s ", "много" );
break;
default:
printf( "%s ", "чрезмерно" );
case 5:
printf( "%s", "много " );
}
printf( "\n" );
}
return 0;
}
Код: Выделить всё
bash-4.2$ ./exe3
1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6,
1 : мало
2 : мало
3 : нормально
4 : много
5 : много
6 : чрезмерно много
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: язык C в Linux: вопросы начального уровня
Последняя на сегодня группа развлечений - вызовы функций:
И что из этого получается:
Код: Выделить всё
bash-4.2$ cat 4.c
#include <stdio.h>
typedef int (*summ_t) ( int );
int summ2( int x ) { return x + 2; }
int summ3( int x ) { return x + 3; }
int summ4( int x ) { return x + 4; }
summ_t funcs[] = { summ2, summ3, summ4 };
int call( summ_t func, void *data ) {
return func( *(int*)data );
}
void set1( int x ) { x++; }
void set2( int* x ) { (*x)++; }
//------------------------------------------
#define N 10
typedef struct {
int x[ N ];
} astruct_t;
astruct_t revers( astruct_t s ) {
int n, i, j;
n = sizeof( s ) / sizeof( int );
for( i = 0, j = n - 1; i < j; i++, j-- ) {
int var = s.x[ i ];
s.x[ i ] = s.x[ j ];
s.x[ j ] = var;
}
return s;
}
void show_ba( astruct_t* b, astruct_t* a ) {
int i;
printf( "before: " );
for( i = 0; i < N; i++ )
printf( "%d%s", b->x[ i ], i != N - 1 ? ", " : "" );
printf( " | after: " );
for( i = 0; i < N; i++ )
printf( "%d%s", a->x[ i ], i != N - 1 ? ", " : "" );
printf( "\n" );
}
//------------------------------------------
void mod( astruct_t* s ) {
int n = sizeof( *s ) / sizeof( int );
void pow2( void ) {
int i;
for( i = 0; i < n; i++ )
s->x[ i ] *= s->x[ i ];
}
pow2();
return;
}
//------------------------------------------
// функции и вызовы:
int main () {
int i;
//------------------------------------------
for( i = 0; i < sizeof( funcs ) / sizeof( funcs[ 0 ] ); i++ )
printf( "%d ", funcs[ i ]( i ) );
printf( "\n" );
//------------------------------------------
summ_t summ2_2 = summ2;
printf( "%d ", summ2_2( 7 ) );
for( i = 0; i < sizeof( funcs ) / sizeof( funcs[ 0 ] ); i++ ) {
summ2_2 = funcs[ i ];
printf( "%d ", summ2_2( 7 ) );
}
printf( "\n" );
//------------------------------------------
i = 3;
int *pi = &i;
printf( "косвенный вызов: %d\n", call( summ3, &i ) );
set1( i );
printf( "передача параметра: по значению -> %d,", i );
set2( pi );
printf( " по ссылке -> %d\n", i );
//------------------------------------------
astruct_t before = {{ 1, 2, 3, 4, 5, 6, 7 }},
after = {{ 10*(0) }};
show_ba( &before, &after );
printf( "revers ... ... ...\n" );
after = revers( before );
show_ba( &before, &after );
//------------------------------------------
after = before;
mod( &after );
printf( "вложенные описания функций (GCC):\n" );
show_ba( &before, &after );
//------------------------------------------
return 0;
}
Код: Выделить всё
bash-4.2$ ./exe4
2 4 6
9 9 10 11
косвенный вызов: 6
передача параметра: по значению -> 3, по ссылке -> 4
before: 1, 2, 3, 4, 5, 6, 7, 0, 0, 0 | after: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
revers ... ... ...
before: 1, 2, 3, 4, 5, 6, 7, 0, 0, 0 | after: 0, 0, 0, 7, 6, 5, 4, 3, 2, 1
10
вложенные описания функций (GCC):
before: 1, 2, 3, 4, 5, 6, 7, 0, 0, 0 | after: 1, 4, 9, 16, 25, 36, 49, 0, 0, 0
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: язык C в Linux: вопросы начального уровня
Кроме того, на GCC в Linux "свет клином не сошёлся" (особенно последний 1-2 года ), поэтому всё это можно (попробовать!) собрать новым компилятором Clang:
... и убедиться, что не все расширения GCC Clang готов проглотить, в частности, вложенные определения функций ему не понравились... Или, по крайней мере, это не так просто, и должно оговариваться как-то опциями.
Иначе не очень понятно, как они тогда с помощью Clang скомпилировали ядро Linux, о чём сообщалось несколько месяцев назад?
Но здесь же можно убедиться, что программы, собранные Clang, выполняются точно так же как GCC, а заодно можно их сравнить по параметрам...
Хотя бы, для начала, в том, что размером то они отличаются :
P.S. Для любителей поразвлекаться архив всего рассказанного выше - прилагается:
Код: Выделить всё
bash-4.2$ make clang
clang -xc -Wall 1.c -o exe1l
clang -xc -Wall 2.c -o exe2l
clang -xc -Wall 3.c -o exe3l
clang -xc -Wall 4.c -o exe4l
4.c:50:21: error: expected ';' at end of declaration
void pow2( void ) {
^
;
1 error generated.
make: *** [exe4l] Ошибка 1
Иначе не очень понятно, как они тогда с помощью Clang скомпилировали ядро Linux, о чём сообщалось несколько месяцев назад?
Но здесь же можно убедиться, что программы, собранные Clang, выполняются точно так же как GCC, а заодно можно их сравнить по параметрам...
Хотя бы, для начала, в том, что размером то они отличаются :
Код: Выделить всё
bash-4.2$ ls -l exe*
-rwxrwxr-x 1 olej olej 5206 окт. 9 21:52 exe1
-rwxrwxr-x 1 olej olej 5074 окт. 9 21:48 exe1l
-rwxrwxr-x 1 olej olej 6187 окт. 9 21:52 exe2
-rwxrwxr-x 1 olej olej 6155 окт. 9 21:48 exe2l
-rwxrwxr-x 1 olej olej 5545 окт. 9 21:52 exe3
-rwxrwxr-x 1 olej olej 5430 окт. 9 21:48 exe3l
-rwxrwxr-x 1 olej olej 7233 окт. 9 21:52 exe4
- Вложения
-
- examples.tgz
- (2.95 КБ) 698 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: язык C в Linux: вопросы начального уровня
Подсказали (в тему):
- есть такая книжка (даже в переводе):
(как утверждает человек, которому я не могу не доверять - это лучший сборник задач)
Вот электронный вариант именно самого задачника: А.Фьюэр, Задачи по языку С.
Пользуйтесь!
P.S. Мне сообщили, что в некоторых браузерах (Safari на MacOS) этот URL не открывается (что-то в записях DNS серверов намудрено).
Этот URL - это ХПИ (Харьковский Политехнический Институт) ... сейчас он как-то по-другому называется ... университе-е-е... (но DNS нормально зарегистрировать не в состоянии).
Тогда можете открывать этот текст по IP адресу:
- есть такая книжка (даже в переводе):
Она вдвое толще, чем оригинал K&R - это те задачи и упражнения, что Фьэр добавил.Керниган Б., Ритчи Д., Фьэр А.
Язык программирования Си. Задачи по языку Си
Пер.с англ. Д.Б.Подшивалова и В.А.Иващенко. -
М.:Финансы и статистика, 1985. - с.193-278.
(как утверждает человек, которому я не могу не доверять - это лучший сборник задач)
Вот электронный вариант именно самого задачника: А.Фьюэр, Задачи по языку С.
Пользуйтесь!
P.S. Мне сообщили, что в некоторых браузерах (Safari на MacOS) этот URL не открывается (что-то в записях DNS серверов намудрено).
Этот URL - это ХПИ (Харьковский Политехнический Институт) ... сейчас он как-то по-другому называется ... университе-е-е... (но DNS нормально зарегистрировать не в состоянии).
Тогда можете открывать этот текст по IP адресу:
Код: Выделить всё
$ nslookup khpi-iip.mipk.kharkiv.edu
Server: 192.168.1.1
Address: 192.168.1.1#53
Non-authoritative answer:
Name: khpi-iip.mipk.kharkiv.edu
Address: 194.44.157.122
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: язык C в Linux: вопросы начального уровня
Olej писал(а): (как утверждает человек, которому я не могу не доверять - это лучший сборник задач)
Это из предисловия к этому сборнику задач, которое само по себе интересно прочитать.Процесс изучения языка программирования можно представить как последовательное прохождение трех этапов (каждый этап, несомненно, может повторяться неоднократно). Первый этап состоит в освоении синтаксиса языка, по крайней мере настолько, что транслятор перестает "ругаться", обнаружив в вашей программе бессмысленные конструкции. Второй этап состоит в осмыслении правильно построенных транслятором конструкций языка. На третьем этапе вырабатывается определенный стиль программирования, соответствующий духу языка, т.е. умение писать ясные, краткие и правильные программы.
Головоломки в этой книге предназначены для того, чтобы помочь читателю на втором этапе обучения языку. Они бросают вызов искусству владения читателем основными правилами языка, заводят его в "редко посещаемые закоулки" языка, подводят к граничным условиям и знакомят с немногими откровенными ловушками. (Конечно, С, как всякий язык программирования, имеет свою долю неясностей, которая познается на опыте.)
Примеры этой книги не следует рассматривать как образцы хорошего программирования. Но то, что делает программу плохой, может головоломку сделать интересной, это скажем:
- двусмысленность выражений, требующая для их интерпретации обращения к описанию языка;
- сложность структуры; структуру данных и структуру программы нелегко удержать в голове;
- неочевидность конструкций, возникающая при использовании их нестандартным способом.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: язык C в Linux: вопросы начального уровня
Там вообще шикарная (по подборке) библиотека: Каталог библиотеки кафедры "Информатика и интеллектуальная собственность"Olej писал(а):Этот URL - это ХПИ (Харьковский Политехнический Институт) ... сейчас он как-то по-другому называется ...
- по операционным системам
- ... особенно по UNIX
- особенно все знаменитые статьи Эдсгара Дэйкстры в переводе на русский - это обязаны все читать!
- и особенно Э.Дейкстра Взаимодействие последовательных процессов, что есть вообще просто классика!
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: язык C в Linux: вопросы начального уровня
Наблюдаемое с этим URL не поддаётся объяснению, это нельзя понять:Olej писал(а): P.S. Мне сообщили, что в некоторых браузерах (Safari на MacOS) этот URL не открывается (что-то в записях DNS серверов намудрено).
Этот URL - это ХПИ (Харьковский Политехнический Институт) ... сейчас он как-то по-другому называется ... университе-е-е... (но DNS нормально зарегистрировать не в состоянии).
Тогда можете открывать этот текст по IP адресу:
- обращение из Opera (v.12.16) по имени http://khpi-iip.mipk.kharkiv.edu/librar ... index.html заканчивается ошибкой 404
- обращение из Firefox (v.24.0) , в тот же момент времени, по http://khpi-iip.mipk.kharkiv.edu/librar ... index.html - ОК и мгновенно, влёт...
- обращение из Opera по имени (IP) http://194.44.157.122/library/extent/pr ... index.html - всё OK
Я такого цирка ещё не видел
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 4 гостя