When you write code in the embedded 1C language, every value — whether it's a number, a string, or a reference to a directory item — lives somewhere. It takes up space in RAM, has a certain type and obeys specific rules. Understanding how variables and data types are arranged in 1C — this is the foundation, without which it is impossible to write reliable and productive code. In this article, we will analyze everything in order: from declaring variables to the intricacies of working with composite types.

What is a variable in 1C?
A variable is a named area of memory in which a value is stored. In 1C, variables are dynamically typed: you do not need to specify in advance what type of data will be in it. The same variable can first contain a number, then a string, and then a date.
You can declare a variable explicitly using the Перем keyword, or implicitly — simply by assigning it a value:
// Explicit declaration of the Counter variable;
// Implicit declaration through assignment
Счётчик = 0;
Имя = "Alexey";
ДатаНачала = '20250101';If a variable is declared through Перем, but it has not yet been assigned a value, it contains the special value Неопределено. This is an important point: Неопределено is not zero, not an empty string, and not an error. This is a separate data type that means no value.
Scope: where the variable lives
In 1C, there are three levels of visibility for variables.
Module variables are declared at the very beginning of the module (before procedures and functions) through Перем. They are available from any procedure and function of this module and exist as long as the module itself exists. This is an analogue of global variables within a single object.
Local variables are created within a procedure or function. They are born when called and die when they exit. The memory they occupied is released automatically.
Export variables are the module variables marked with the keyword Экспорт. They are available from the outside - from other modules and forms:
Перем ГлобальнаяНастройка Экспорт;Tip: If you store a large table of values in a module variable, it will hang in memory for the entire lifetime of the form or processing. A local variable inside a procedure is a much safer choice if the data is only needed at runtime.
Primitive data types
The 1C platform provides several basic (primitive) types that are the building blocks for everything else.
Number - stores integers and fractional numbers. The maximum number of digits is 38, of which up to 10 can be after the decimal point. 1C uses decimal arithmetic, not binary floating point, like most programming languages. This means that 0.1 + 0.2 in 1C will give exactly 0.3, and not 0.30000000000000004, as in JavaScript or Python. For financial calculations, this is a critical property:
Цена = 1500.50;
Количество = 3;
Сумма = Цена * Количество; // 4501.50 — exactly, without errorsLine — a sequence of characters in UTF-16 encoding. Strings in 1C are immutable: each concatenation operation creates a new string in memory. If you glue thousands of rows in a loop, each iteration generates a new object, and the old one waits for the garbage collector. For mass text assembly, it is better to use the entry in ТекстовыйДокумент or form parts in an array, and then combine:
// Bad - quadratic complexity in memory
Результат = "";
Для Каждого Элемент Из Коллекция Цикл
Результат = Результат + Элемент + ", ";
КонецЦикла;
// Better - linear complexity
Части = Новый Массив;
Для Каждого Элемент Из Коллекция Цикл
Части.Добавить(Элемент);
КонецЦикла;
Результат = СтрСоединить(Части, ", ");Date — stores the date and time to the nearest second. An empty date is '00010101', not Неопределено. This is a common source of errors: checking Если Дата = Неопределено will not catch an empty date. Correct check:
Если ДатаДокумента = '00010101' Тогда
// Date is not filled in End If;Boolean — takes the values Истина or Ложь. In conditional expressions, 1C does not perform implicit type conversion: the number 0 does not automatically turn into Ложь, as in JavaScript. You need to write an explicit comparison.
Undefined — a special type with a single value. Used as a marker of no value, returned when referring to a non-existent match key, when reading empty props and in other similar situations.
Null — another special type associated with databases. It appears when working with query results, when the left connection is used and there is no corresponding entry in the attached table. Null and Неопределено are different things, and they should not be confused.

Reference types: what is actually in the variable?
When you receive a directory item or document, the variable does not store the entire object, but a link — a unique identifier (UUID), by which the platform can find data in the database:
СсылкаНаТовар = Справочники.Товары.НайтиПоКоду("00001");The variable СсылкаНаТовар contains a reference of the type СправочникСсылка.Товары. This is a compact object — essentially, a wrapper over the GUID. The data itself (name, price, balances) is not loaded into memory. They will be pulled from the database only when the requisite is first accessed:
// This is where the database is accessed
Наименование = СсылкаНаТовар.Наименование;This is called lazy loading, and it has a downside. If you go through a thousand links in a loop and read the props of each one through a dot, the platform will make a thousand separate queries to the database. The correct solution is to receive data in batches through a request:
// Bad — 1000 database accesses For Each Link From ArrayLinks Cycle
Наименование = Ссылка.Наименование; // query to the database on each iteration End of Cycle;
// Good — 1 request to the database
Запрос = Новый Запрос;
Запрос.Текст = "SELECT Name FROM Reference.Book.Products WHERE Link (&List)";
Запрос.УстановитьПараметр("List", МассивСсылок);
Результат = Запрос.Выполнить().Выгрузить();Important: A reference (СправочникСсылка) is a "pointer" to data that is read-only. An object (СправочникОбъект) is a complete copy of the data loaded into memory that can be modified and written. The object is heavier than the link. If you receive objects in a loop, but are not going to change them — use links and queries.
// We get the object — all data is loaded into memory
ОбъектТовара = СсылкаНаТовар.ПолучитьОбъект();
ОбъектТовара.Наименование = "New name";
ОбъектТовара.Записать();Composite type: one field — many possibilities
In 1C metadata, a property can have a composite type. For example, the "Owner" field in the document can be of both СправочникСсылка.Организации and СправочникСсылка.ФизическиеЛица types. The platform stores both the value itself and information about its type in this field.
To work with composite types, use the ОписаниеТипов object:
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Number"));
МассивТипов.Добавить(Тип("Line"));
ОписаниеДопустимыхТипов = Новый ОписаниеТипов(МассивТипов);You can check the current value type in the variable using the ТипЗнч() function:
Если ТипЗнч(Значение) = Тип("Number") Тогда
// Work as with a number Otherwise If TypeCh (Value) = Type("ReferenceLink.Goods") Then // We work as with a link End If;Composite types are convenient, but they have their price. In the database, a field with a composite type is stored less efficiently than a field with one fixed type. If the field always contains a value of one type, it is better to specify it in the configurator - this will save space and speed up queries.
Collections: arrays, structures, and matches
In addition to primitive and reference types, 1C has a set of universal collections that are used everywhere.
Array — an ordered set of values with index access. Indexing starts from zero. It can contain elements of any type at the same time:
Список = Новый Массив;
Список.Добавить(42);
Список.Добавить("text");
Список.Добавить(ТекущаяДата());Structure — a set of "key-value" pairs, where the keys are the strings specified during creation. The structure is convenient for passing named parameters:
Параметры = Новый Структура;
Параметры.Вставить("Organization", СсылкаОрганизации);
Параметры.Вставить("Period", ТекущаяДата());Compliance — also key-value pairs, but the key can be any type of value, including links. The match works like a hash table:
КэшНаименований = Новый Соответствие;
КэшНаименований.Вставить(СсылкаНаТовар, "Milk 3.2%");
Наименование = КэшНаименований.Получить(СсылкаНаТовар); // "Milk 3.2%"Nuance: The Получить method of the match returns Неопределено if the key is not found, and does not cause an error. This must be taken into account when writing conditions.
Table of values — the most powerful collection in 1C. In essence, it is a temporary table in memory with rows and typed columns. Value tables are actively used for data processing, reporting and exchange between modules:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Product", Новый ОписаниеТипов("ReferenceLink.Products"));
ТЗ.Колонки.Добавить("Quantity", Новый ОписаниеТипов("Number"));
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Товар = СсылкаНаТовар;
НоваяСтрока.Количество = 10;A table of values can take up a significant amount of memory. If you load a query result with a million rows into it, all this information will be in the server's RAM. For large amounts of data, it is better to process the query result in batches using Выборка, rather than loading everything into the table at once.
Typecasting and pitfalls
1C performs implicit type conversion in some operations, and this can lead to unexpected results:
// Line + Number — there will be an error!
Результат = "Total: " + 100; // Type conversion error
// Correct — explicit conversion
Результат = "Total: " + Строка(100); // Total: 100
// Comparison of different typesIf 0 = False Then // False - types do not matchEndIf;
Если 0 = "" Тогда // Also FalseEndIf;Explicit conversion functions are your friends: Число(), Строка(), Дата(), Булево(). Use them whenever you need to convert a value, and don't rely on the platform's automation.
Passing parameters: by value and by reference
In 1C, the parameters of procedures and functions are passed by reference by default. This means that if you pass an array to a procedure and add elements to it, the calling code will see these changes:
Процедура ДобавитьЭлемент(МойМассив)
МойМассив.Добавить("new item");
КонецПроцедуры
Данные = Новый Массив;
ДобавитьЭлемент(Данные);
// The data now contains a "new item"If you want to protect the original from changes, use the keyword Знач:
Процедура БезопаснаяОбработка(Знач МойМассив)
МойМассив.Добавить("this will not affect the original");
КонецПроцедурыHowever, for primitive types (number, string, date, boolean), the "by reference" transfer works differently: reassigning a parameter within a procedure does not affect the external variable. Changes are visible only for mutable objects — arrays, structures, tables of values.
Why is all this important?
Understanding variables and data types is not an academic exercise. It directly affects the quality of your code. Knowing that strings are immutable will save you from creating thousands of intermediate objects in memory. Understanding the difference between a reference and an object will prevent hundreds of unnecessary database queries. Understanding how composite types work will help you design the metadata structure correctly. And a clear idea of the scope will protect you from memory leaks in the server code.
Every time you declare a variable, you make an architectural decision: what to store, where to store it, and for how long. The better you understand the internal mechanics of the platform, the more confident and efficient your code will be.
If you want to study programming systematically - from the basics to advanced topics - take a look at the application Code. This is an educational platform with step-by-step courses in Python, JavaScript, HTML, CSS and other languages that will help you build a solid foundation of knowledge.
And if you have any questions or want to discuss the material with other developers, join our Telegram channel, where more than 2000 participants share their experience and help each other grow in their profession.
