Язык С: переменные
Переменная — это не что иное, как именованная область памяти, которой могут манипулировать программы. Каждая переменная в языке C характеризуется:
- типом, определяющим размер и расположение памяти переменной;
- диапазоном значений, которые могут храниться в этой памяти;
- набором операций, которые можно применить к переменной.
Имя переменной может состоять из букв, цифр и символа подчеркивания. Оно должно начинаться либо с буквы, либо с символа подчеркивания. Строчные и заглавные буквы различаются, поскольку C чувствителен к регистру. Выделим основные типы переменных:
- char — целочисленный тип, представляющий обычно один октет (один восьмибитовый байт);
- int — наиболее естественный размер целого числа для компьютера;
- float — значение с плавающей запятой одинарной точности;
- double — значение с плавающей запятой двойной точности;
- void — представляет отсутствие типа.
Язык C также позволяет определять другие типы переменных (перечисление, указатель, массив, структура, объединение и т.д.), которые будут рассмотрены в последующих разделах. Здесь уделим внимание только основным типам переменных.
Определение переменных
Определение переменной указывает компилятору, где и какой объем памяти нужно создать для этой переменной. Определение переменных задает тип данных и содержит список одной или нескольких переменных этого типа следующим образом:
Здесь type должен быть допустимым типом данных языка C, включая char , w_char , int , float , double , bool или любой объект, определяемый пользователем; а variable_list может состоять из одного или нескольких имен идентификаторов, разделенных запятыми. Ниже показаны некоторые допустимые объявления:
Строка int i, j, k; объявляет и определяет переменные i , j и k ; которые инструктируют компилятор создать переменные с именами i , j и k типа int .
Переменные могут быть инициализированы (им присваивается начальное значение) в их объявлении. Блок инициализации состоит из знака равенства, за которым следует константное выражение, как показано ниже:
Определение без инициализации: переменные со статической длительностью хранения неявно инициализируются со значением NULL (все байты имеют значение 0 ); начальное значение всех остальных переменных не определено.
Объявление переменных
Объявление переменной подтверждает компилятору, что существует переменная с заданным типом и именем. Получив такое подтверждение, компилятор может приступить к дальнейшей компиляции, не требуя полной информации о переменной. Определение переменной имеет значение только во время компиляции: компилятору необходимо фактическое определение переменной во время сборки программы.
Объявление переменной полезно при использовании нескольких файлов и определении переменной в одном из файлов, который будет доступен во время сборки программы. Можно использовать ключевое слово extern для объявления переменной в любом месте. Хотя в своей программе вы можете объявлять переменную несколько раз, она должна быть определена только один раз в файле, функции или блоке кода.
Пример
Рассмотрим пример, где переменные были объявлены в самом верху, но определены и инициализированы внутри главной функции.
Когда приведенный выше код компилируется и выполняется, выдается следующий результат:
Тот же принцип применим к объявлению функции, когда вы указываете имя функции во время ее объявления, а ее фактическое определение может быть дано в любом другом месте. Например:
L-значения и R-значения
В языке C есть два вида выражений:
- L-значения. Выражения, которые ссылаются на область памяти, называются выражениями l-значения. L-значение может появляться как в левой, так и в правой части присваивания.
- R-значения. Термин r-значение относится к значению данных, которое хранится по некоторому адресу в памяти. R-значение — это выражение, которому не может быть присвоено значение, что означает, что r-значение может появляться только в правой части присваивания.
Переменные — это l-значения, поэтому они могут появляться в левой части присваивания. Числовые литералы являются r-значениями, поэтому их нельзя присвоить и они не могут появляться в левой части. Посмотрите на следующие допустимые и недопустимые операторы:
Переменные в C#
Переменная — именованная область памяти. Переменные в программах используются для хранения данных.
Как объявляются переменные
В этом примере мы объявили переменную age типа int , которая в качестве значения может содержать только целые числа.
Мы можем присвоить переменной значение позже следующим образом:
Но переменную можно инициализировать и сразу при объявлении:
В этом примере мы объявляем переменную age типа int и в это же время инициализируем ее значением 24.
Мы также можем менять значения переменных. Например:
Мы поменяли значение переменной age с 24 на 35.
Переменные в C# объявляются до их использования — это значит, что до присвоения переменной значения программа должна знать ее имя и тип. Поэтому C# называют строго типизированным языком.
Тип данных переменной после объявления нельзя изменить в пределах ее области видимости. Область видимости — это блок кода, в переменная доступна для использования. Если вы не поняли предыдущее предложение, не переживайте, об областях видимости мы расскажем в следующих главах.
Так — не получится
Неявно типизированные переменные
В C# можно объявить переменную без явного задания ее типа данных с помощью ключевого слова var . Такие переменные называются неявно типизированными локальными.
Переменные, объявленные с помощью ключевого слова var , должны быть инициализированы во время объявления.
Компилятор выводит тип данных из значения, которое присваивается переменной. В примере выше value типа int . То же самое можно написать и так:
Здесь можно узнать больше о неявно типизированных локальных переменных.
Правила именования переменных
Есть некоторые правила, которых мы должны придерживаться при именовании переменных:
- Имя переменной может содержать только буквы (строчные и прописные), нижнее подчеркивание _ и цифры.
- Имя переменной должно начинаться с буквы, нижнего подчеркивания или символа @ .
- C# чувствителен к регистру: age и Age — две разные переменные.
- Имя переменной не должно совпадать с ключевыми словами. for , if или using не могут быть именем переменной.
Имена переменных
Замечания
Допустимо. Лучший способ называния переменных для членов с модификатором private .
C#: требования и рекомендации по написанию кода
Не так давно в комментариях к топику AlexS высказал идею использования соглашения об оформлении на Хабре кода примеров темы .Net написанных на C#.
Я немного поизучал имеющиеся предложения из этих источников:
submain.com/blog/FreeCVBNETCodingGuidelinesEbookDownload.aspx
idesign.net/idesign/DesktopDefault.aspx
и скомпилировал черновик который описывает самые базовые правила оформления кода написанного на C#.
Предлагаю:
— обсудить этот черновик;
— внести в него все необходимые изменения;
— утвердить как стандарт написания C# кода на Хабре.
Более того, предлагаю создать документ, который можно было бы предложить как рекомендации habrahabr comunity для всех других программистов C#.
Под катом вы найдете текст черновика. Предлагаю всем желающим обсудить его и подвергнуть надлежащей правке.
1. Требования
1.1 Pascal casing
namespace SampleNamespace
<
enum SampleEnum
<
FirstValue,
SecondValue
>
struct SampleStruct
<
public int FirstField;
public int SecondField;
>
interface ISampleInterface
<
void SampleMethod();
>
public class SampleClass: SampleInterface
<
const int SampleConstValue = 0xffffff;
readonly int SampleReadonlyField;
public int SampleProperty
<
get ;
set ;
>
public int SamplePublicField;
SampleClass()
<
SampleReadonlyField = 1;
>
delegate void SampleDelegate();
event SampleDelegate SampleEvent;
public void SampleMethod()
<
>
>
> * This source code was highlighted with Source Code Highlighter .
1.2 Camel casing
protected int sampleProtectedField;
int SampleMethod( int sampleArgument)
<
int sampleLocalVariable;
> * This source code was highlighted with Source Code Highlighter .
1.3 Суффиксы и префиксы
public class SampleException: System. Exception
<
public SampleException()
<
>
>
interface ISample
<
void SampleMethod();
>
[System. AttributeUsage (System. AttributeTargets .All, Inherited = false , AllowMultiple = true )]
sealed class SampleAttribute: System. Attribute
<
public SampleAttribute()
<
>
> public delegate void AnswerCreatedEventHandler( object sender, AnswerCreatedEventArgs e);
public class AnswerCreatedEventArgs: EventArgs
<
public int СreatedId;
public int ParentId;
public string CreatorName;
> * This source code was highlighted with Source Code Highlighter .
1.4 Аббревиатуры
class HttpUtil
<
> * This source code was highlighted with Source Code Highlighter .
2. Рекомендации
2.1 Именование методов
В частном случае, для методов, которые возвращают значение, используйте в паре глагол-объект для глагола «Get», а для объекта – описание возвращаемого значения.
2.2 Переменные, поля и свойства
• При именовании переменных избегайте использования сокращенных вариантов вроде I и t, используйте index и temp. Не используйте венгерскую нотацию или используйте ее только для закрытых членов. Не сокращайте слова, используйте number, а не num.
• Рекомендуется для имен элементов управления указывать префиксы, описывающие тип элемента. Например: txtSample, lblSample, cmdSample или btnSample. Эта же рекомендация распространяется на локальные переменные сложных типов: ThisIsLongTypeName tltnSample = new ThisIsLongTypeName();
• не используйте публичных или защищенных полей, вместо этого используйте свойства;
• используйте автоматические свойства;
• всегда указывайте модификатор доступа private, даже если разрешено его опускать;
• всегда инициализируйте переменные, даже когда существует автоматическая инициализация.
2.3 Дополнительные рекомендации
2.4 Объем кода
• избегайте файлов с более чем 500 строками кода;
• избегайте методов с более чем 200 строками кода;
• избегайте методов с более чем 5 аргументами, используйте структуры для передачи большого числа параметров;
• одна строка кода не должна иметь длину более 120 символов.
Гайд по оформлению кода на С++ от Стэнфордского университета
Стэнфордский университет представил гайд по основным стандартам оформления кода на С++. Умение корректно оформить ваш код является ценным навыком, так как это в разы облегчает работу других. Также у нас есть подобная статья, посвящённая написанию самодокументируемого кода.
Пробелы и отступы
Отделяйте пробелами фигурные скобки:
Ставьте пробелы между операторами и операндами:
Когда строка становится длиннее 100 символов, разделите её на две, сделав перевод на новую строку после оператора, и продолжайте писать:
Оставляйте пустые линии между функциями и между группами выражений:
Названия и переменные
Давайте переменным описательные имена, такие как firstName или homeworkScore . Избегайте однобуквенных названий вроде x или c , за исключением итераторов вроде i .
Называйте переменные и функции, используя верблюжийРегистр . Называйте классы ПаскальнымРегистром , а константы — в ВЕРХНЕМ_РЕГИСТРЕ . Узнать подробнее про верблюжий регистр вы можете в этой статье.
Если переменная используется лишь внутри определенного if , то делайте её локальной, объявляя в том же блоке кода, а не глобальной.
Выбирайте подходящий тип данных для ваших переменных. Если переменная содержит лишь целые числа, то определяйте её как int , а не double .
Используйте текстовую строку, стандартную для C++, а не С. С++ путает тем, что имеет два вида текстовых строк: класс string из С++ и старый char* (массив символов) из С:
Если определенная константа часто используется в вашем коде, то обозначьте её как const и всегда ссылайтесь на данную константу, а не на её значение:
Никогда не объявляйте изменяемую глобальную переменную. Глобальными переменными должны быть только константы. Вместо того, чтобы делать значение глобальным, сделайте его параметром и возвращайте значение, когда необходимо:
Базовые выражения С++
С++ основан на С, поэтому всегда есть вариант решить задачу «путем С++» и «путем С». Например, когда вы желаете вывести что-либо на системную консоль, вы можете сделать это «путем С++» , использовав оператор вывода cout , в то время как «путем С» вы бы использовали глобальную функцию вроде printf :
Частенько затрудняетесь с выбором между for и while ? Используйте цикл for , когда вы знаете количество повторений, а цикл while , когда количество повторений неизвестно:
Когда используете операторы управления вроде if / else , for , while , всегда используйте < >и соответствующие отступы, даже если тело всего оператора управления состоит лишь из одной строки:
Старайтесь избегать использования выражений break или continue . Используйте их только в том случае, если это абсолютно необходимо.
В C++ есть функция exit , которая немедленно завершает программу. Настоятельно не рекомендуется использовать данную функцию. Программа всегда должна заканчиваться естественно, достигая оператора return функции main .
Используя выражения if / else , подобающе выбирайте между разнообразными if и else шаблонами в зависимости от условий, относящихся к друг другу. Избегайте излишних тестов if :
Если у вас есть выражение if / else , которое возвращает логическое значение, возвращайте результаты теста напрямую:
Никогда не проверяйте значения логического типа, используя == или != с true или false :
Чрезмерность
Если вы используете один и тот же код дважды или более, то найдите способ удалить излишний код, чтобы он не повторялся. К примеру, его можно поместить во вспомогательную функцию. Если повторяемый код похож, но не совсем, то постарайтесь сделать вспомогательную функцию, которая принимает параметры и представляет разнящуюся часть:
Переместите общий код из выражения if / else , чтобы он не повторялся:
Комментарии
Заглавный комментарий. Размещайте заглавный комментарий, который описывает назначение файла, вверху каждого файла. Предположите, что читатель вашего комментария является продвинутым программистом, но не кем-то, кто уже видел ваш код ранее.
Заголовок функции / конструктора. Разместите заголовочный комментарий на каждом конструкторе и функции вашего файла. Заголовок должен описывать поведение и / или цель функции.
Параметры / возврат. Если ваша функцию принимает параметры, то кратко опишите их цель и смысл. Если ваша функция возвращает значение — кратко опишите, что она возвращает.
Исключения. Если ваша функция намеренно выдает какие-то исключения для определенных ошибочных случаев, то это требует упоминания.
Комментарии на одной строке. Если внутри функции имеется секция кода, которая длинна, сложна или непонятна, то кратко опишите её назначение.
TODO. Следует удалить все // TODO комментарии перед тем, как заканчивать и сдавать программу.
Эффективность
Вызывая большую функцию и используя результат несколько раз, сохраните результат в переменной вместо того, чтобы постоянно вызывать данную функцию:
Функции и процедурное проектирование
Хорошо спроектированная функция имеет следующие характеристики:
- Полностью выполняет четко поставленную задачу;
- Не берет на себя слишком много работы;
- Не связана с другими функциями бесцельно;
- Хранит данные максимально сжато;
- Помогает распознать и разделить структуру программы;
- Помогает избавиться от излишков, которые иначе присутствовали бы в программе.
Используйте параметры, чтобы отправлять информацию из функции или когда функции нужно возвратить несколько значений. Не используйте параметры без необходимости. Заметьте, что a , b , и с не являются параметрами в нижеприведенной функции, так как это не нужно:
Когда требуется вернуть значение из функции, используйте значение return :
Отправляя объект в функцию как параметр, вы должны передавать его по ссылке, так как если он будет передан как значение, то будет скопирован весь объект. Копирование объектов требует больших затрат памяти.
Используйте ссылочные переменные, а не указатели. Одна из причин — это то, что ссылочные переменные, в отличие от указателей, не могут принимать значение NULL :
Если вы передаете объект в функцию и код не изменит вида объекта — передайте его как const -ссылку:
Избегайте «цепных» вызовов, когда множество функций вызывают друг друга по цепочке, не возвращая значение в main . Убедитесь, что main является кратким описанием всей программы:
Проектирование классов
Инкапсуляция. Отделяйте ваши объекты, делая все поля данных в вашем классе private :
.h vs .cpp. Всегда размещайте объявления классов и их частей в собственные файлы, ClassName.h . Всегда сворачивайте файлы объявления классов .h в блок препроцессоров #ifndef / define / endif , чтобы избежать множественных объявлений одного класса:
class vs struct. Всегда используйте class , только если вы не создаете очень маленький и простой вид данных, для которого нужны лишь несколько публичных переменных и, возможно, конструктор для их инициализации.
Избегайте ненужных полей. Используйте поля, чтобы хранить важные данные о ваших объектах, но не временные значения, которые используются единожды.