Замечательные лекции по С! В эту лекцию можно еще добавить о миксе (смешивании) квалификаторов const и extern. Их можно использовать вместе. Обычный шаблон таков: file.h: extern const int a_global_var; file.c: #include "file.h" const int a_global_var = /* константное значение */; И для полноты картины можно также поговорить о квалификаторах inline и volatile (они тоже миксуются)
"в прототипе функции имена переменных можно опускать, т.к. для компилятора это не имеет никакого значения" Да, но как говорится - есть нюанс. Если в функции в качестве параметров используется двумерный массив переменной длины. Например: void funct(int n, int ar[][n]) и если в прототипе такой функции удалить имена параметров void funct(int, int[][]) то будет ошибка компиляции, т.к. компилятор не сможет определить размерность массива. Поэтому для этого существует такая форма записи прототипа: void funct(int, int[][*])
Небольшая тонкость про прототип функции с языке Си. Прототип int f(); задает функцию c именем f, возвращающую значение int c неопределенным набором параметров (не обязательно пустым). Чтобы задать функцию именно с пустым набором параметров нужно написать int f(void); В этом отличие от С++, где int f(); и int f(void); задают функцию без параметров.
Спасибо за урок. 1. В стандарте языка Си нет определений понятий "глобальная" и "локальная" переменная. Я думаю эти два термина ненаучны. Какое настоящее название? 2. Я правильно понял, что это есть три характеристики переменной: класс хранения (где выделить память), время жизни (когда деаллоцировать), и область видимости (откуда есть доступ)?
1. В той среде программистов, что я обитаю, говорят глобальные и локальные - это очень удобно. По научному, может быть что то вроде: переменная области видимости модуля с внешним связыванием (или внутренним связыванием). Но я сомневаюсь, что на практике так будут говорить )) 2. В целом да, возможны нюансы.
Сергей, помогите разобраться, почему если до main объявить массив и указатель на него, то в main возможно менять адрес указателя, а если этот указатель на глобальный массив объявить в main, но со словом static, то уже не можем? Почему позволяется менять адрес указателя, объявленного в глобальной области, если по идее, всё что объявлено вне main по умолчанию является статическим? Вот так работает. int a[] = {4,5,6}; int* p = a; int main() { p +=1; printf("%d", *p); return 0; } А вот так не позволяет изменить адрес p. int a[] = {4,5,6}; int main() { static int* p = a; p +=1; printf("%d", *p); return 0; }
Да, все верно, если здесь поставить в компиляторе флаг -Wall, тоже будет предупреждение. Если локальные переменные не инициализированы, то они забиваются шумом, отсюда и это предупреждение.
@@selfedu_rus можно ще бы курс по Пайтону для андроид и дата сайнс, или по автоматизации рутиных операций или по патерном проектировании, а можно новый курс на степике из тех что есть на Ютубе.
Подушню. На самом деле ключевое сдово static не влияет на область видимости, т.к. никакой глобальной области видимости в Си нет🤪 (есть область видимости - блока, прототипа функции, функции, файла/единицы трансляции). А влияет на класс хранения, меняя у переменных определенных в блоке продолжительность хранения с автоматической на статическую, оставляя область видимости в пределах блока, и отсутствие связывания, а у переменных определенных вне функций - меняет внешнее связывание на внутренее, оставляя область видимости в пределах файла, и статическую продолжительность хранения.
Отличный урок !!! Спасибо за изложения высшего класса. Отслеживаю весь ваш вклад в сообщество изучающих программирование в Ютубе.
Замечательные лекции по С!
В эту лекцию можно еще добавить о миксе (смешивании) квалификаторов const и extern. Их можно использовать вместе.
Обычный шаблон таков:
file.h:
extern const int a_global_var;
file.c:
#include "file.h"
const int a_global_var = /* константное значение */;
И для полноты картины можно также поговорить о квалификаторах inline и volatile (они тоже миксуются)
"в прототипе функции имена переменных можно опускать, т.к. для компилятора это не имеет никакого значения"
Да, но как говорится - есть нюанс.
Если в функции в качестве параметров используется двумерный массив переменной длины.
Например:
void funct(int n, int ar[][n])
и если в прототипе такой функции удалить имена параметров
void funct(int, int[][])
то будет ошибка компиляции, т.к. компилятор не сможет определить размерность массива.
Поэтому для этого существует такая форма записи прототипа:
void funct(int, int[][*])
Спасибо. Уровень!
Небольшая тонкость про прототип функции с языке Си. Прототип
int f();
задает функцию c именем f, возвращающую значение int c неопределенным набором параметров (не обязательно пустым). Чтобы задать функцию именно с пустым набором параметров нужно написать
int f(void);
В этом отличие от С++, где int f(); и int f(void); задают функцию без параметров.
спасибо
Хотел увидел уроки по котлину в сравнении с пайтоном, чтоб преподавалрсь в сравнении.
И тот и тот язык очень лаконичный.
Здравствуйте! подскажите пожалуйста как на мак в настройках указывать файл! Очень прошу!
Спасибо за урок.
1. В стандарте языка Си нет определений понятий "глобальная" и "локальная" переменная. Я думаю эти два термина ненаучны. Какое настоящее название?
2. Я правильно понял, что это есть три характеристики переменной: класс хранения (где выделить память), время жизни (когда деаллоцировать), и область видимости (откуда есть доступ)?
1. В той среде программистов, что я обитаю, говорят глобальные и локальные - это очень удобно. По научному, может быть что то вроде: переменная области видимости модуля с внешним связыванием (или внутренним связыванием). Но я сомневаюсь, что на практике так будут говорить ))
2. В целом да, возможны нюансы.
Сергей, помогите разобраться, почему если до main объявить массив и указатель на него, то в main возможно менять адрес указателя, а если этот указатель на глобальный массив объявить в main, но со словом static, то уже не можем? Почему позволяется менять адрес указателя, объявленного в глобальной области, если по идее, всё что объявлено вне main по умолчанию является статическим?
Вот так работает.
int a[] = {4,5,6};
int* p = a;
int main()
{
p +=1;
printf("%d", *p);
return 0;
}
А вот так не позволяет изменить адрес p.
int a[] = {4,5,6};
int main()
{
static int* p = a;
p +=1;
printf("%d", *p);
return 0;
}
у меня на gcc позволяет в обоих случаях, возможно как то ваш компилятор по особенному отрабатывает этот момент?
А как работает например volatile?
2:48 ругается на неинициализированную локальную переменную int var_main (Ошибка С4700, Visual Studio 2019)
int main(void)
{
int var_main;
static int var_st;
printf("var_main = %d, var_st = %d
", var_main, var_st);
return 0;
}
Да, все верно, если здесь поставить в компиляторе флаг -Wall, тоже будет предупреждение. Если локальные переменные не инициализированы, то они забиваются шумом, отсюда и это предупреждение.
Когда вернётесь к урокам по Пайтону?
А что там, вроде все подробно рассказал?
@@selfedu_rus можно ще бы курс по Пайтону для андроид и дата сайнс, или по автоматизации рутиных операций или по патерном проектировании, а можно новый курс на степике из тех что есть на Ютубе.
здравствуйте, у вас будут курсы по аналитике данных?
пока не планирую
@@selfedu_rus :(
Должен ли я изучать язык программирования C перед изучением C++?
C++ мне нужен для изучения Unreal Engine
Формально, вряд-ли нужно его изучать, но конкретно этого автора можно, полезно для понимания
нет, это разные языки
Языки Си - это база для языка С++. Я бы начал с Си.
Подушню. На самом деле ключевое сдово static не влияет на область видимости, т.к. никакой глобальной области видимости в Си нет🤪 (есть область видимости - блока, прототипа функции, функции, файла/единицы трансляции). А влияет на класс хранения, меняя у переменных определенных в блоке продолжительность хранения с автоматической на статическую, оставляя область видимости в пределах блока, и отсутствие связывания, а у переменных определенных вне функций - меняет внешнее связывание на внутренее, оставляя область видимости в пределах файла, и статическую продолжительность хранения.
А в плюсах так же ?