4310

Функции на языке Си

Контрольная

Информатика, кибернетика и программирование

Функции Программы на языке Си обычно состоят из большого числа отдельных функций (подпрограмм). Как правило, эти функции имеют небольшие размеры и могут находиться как в одном, так и в нескольких файлах. Все функции являются глобальными. В языке зап...

Русский

2012-11-16

84 KB

4 чел.

Функции

Программы на языке Си обычно состоят из большого числа отдельных функций (подпрограмм). Как правило, эти функции имеют небольшие размеры и могут находиться как в одном, так и в нескольких файлах. Все функции являются глобальными. В языке запрещено определять одну функцию внутри другой. Связь между функциями осуществляется через аргументы (параметры), возвращаемые значения и внешние переменные.

В общем случае функции в языке Си необходимо объявлять. Объявление функции (т.е. описание заголовка) должно предшествовать ее использованию, а определение функции (т.е. полное описание) может быть помещено как после тела программы (т.е. функции main( )), так и до него. Если функция определена до тела программы, а также до ее вызовов из определений других функций, то объявление может отсутствовать. Описание заголовка функции обычно называют прототипом функции.

Функция объявляется следующим образом:

тип   имя_функции(тип1  имя_параметра_1, тип2  имя_параметра_2, ...);

Тип функции определяет тип значения, которое возвращает функция. Если тип не указан, то предполагается, что функция возвращает целое значение (int). Функция, не возвращающая значение, имеет тип void.

При объявлении функции для каждого ее параметра можно указать только его тип (например: тип функция (int, float, ...), а можно дать и его имя (например: тип функция (int а, float b, ...) ).

В языке Си разрешается создавать функции с переменным числом параметров. Тогда при задании прототипа вместо последнего из них указывается многоточие.

Определение функции имеет следующий вид:

    

тип   имя_функции(тип1   имя_параметра_1, тип2   имя_параметра_2,...)

    {

        тело функции

    }

Параметры в заголовке функции называются формальными.

Вызывается функция в соответствии со следующим синтаксисом:

имя_функции(  выражение_1, выражение_2,...)

Выражения в вызове функции вычисляются и их значения передаются в функцию как фактические значения формальных параметров. Количество, типы, порядок следования формальных параметров должны соответствовать  количеству, типам и порядку следования фактических параметров. Это соответствие определяется на этапе трансляции программы. Вызов функции, возвращающей значение, может располагаться справа от знака присваивания, а также входить в состав выражений и быть аргументом функции, если это позволяет тип возвращаемого функцией значения.

Передача значения из вызванной функции в вызвавшую происходит с помощью оператора возврата return, который записывается в следующем формальном виде:

    return выражение;

Таких операторов в подпрограмме может быть несколько, и тогда они фиксируют соответствующие точки выхода. После слова return можно ничего не записывать - в этом случае вызвавшей функции никакого значения не передается. Оператор return может отсутствовать в функции, которая не возвращает значение в точку своего вызова. В этом случае управление в точку вызова передается по достижении конца тела функции (последняя закрывающая фигурная скобка).

Например:

   

int f(int a, int b)

    {

        if (a > b) { printf("max = %d\n", a); return a; }

        printf("max = %d\n", b); return b;

    }

Вызвать эту функцию можно, например, следующим образом:

    c = f(15, 5);  

    c = f(d, g);    

Вызвавшая функция может при необходимости игнорировать возвращаемое значение, т.е. результат, который возвращает функция, нигде не запоминается и не используется:

    f(d, g);        

В языке Си параметры функции передаются по значению, т.е. вызванная функция получает свою временную копию каждого аргумента.

Пример 1.  Передача аргумента в функцию по значению.

Вычислить куб последовательности целых чисел 0, 2, 4, …18.

#include <stdio.h>

int icube(int ival);   //получение куба числа

int main(void)

{

int k, irez;

for(k=0; k<20; k+=2)

{

 irez=icube(k);

 printf("Куб числа %d \tравен %d\n", k, irez);

}

 return 0;

}

//вычисление куба

int icube(int ival)

{

return(ival*ival*ival);

}

Передача параметров в функцию по значению означает, что вызванная функция не может изменить значение переменной, являющейся фактическим параметром.

Однако это легко сделать, если передавать в функцию не переменные, а их адреса.

Например:

    void swap(int  *a, int  *b)

    {

        int  tmp = *a;

     

        *a = *b;

        *b = tmp;

    }

Вызов swap(&b, &c) (здесь в функцию передаются адреса переменных b и с) приведет к тому, что значения переменных b и c поменяются местами.

Передача параметров в функцию по адресу позволяет также использовать эти параметры для возврата функцией нескольких значений.

Пример 2. Функция возвращает несколько результатов

Написать и протестировать функцию определения полярных координат по ее прямоугольным декартовым. Формулы преобразования

#include <stdio.h>

#include <math.h>

void pol(int, int, float *, float *);   //полярные координаты

int main()

{

float x, y, ro=0, fi=0;

 puts("Введите x");

 scanf("%f", &x);

 puts("Введите y");

 scanf("%f", &y);

pol(x, y, &ro, &fi);

printf("Пол. координата: ro=%f\tfi=%f", ro, fi);

return 0;

}

void pol(int a1, int a2, float *k1, float *k2)

{

*k1=sqrt(a1*a1+a2*a2);

*k2=atan(a2/a1);

}

Функции и массивы

Массивы передаются в функцию по адресу, поскольку имя массива является указателем на его начало. Зная адрес первого элемента массива, функция может изменять элементы массива, сдвигаясь (индексированием) от его начала.

Рассмотрим, как функции можно передать массив в виде параметра. Здесь возможны следующие варианты:

  1.  Параметр описывается как массив.

При этом числовое значение первой размерности можно не указывать.

Например: int a[100], int b[], float c[50][30], double s[][100]

  1.  Параметр описывается как указатель.

Например: int *m, int **m1 .

Независимо от выбранного варианта вызванной функции передается указатель на начало массива.

Пример 3. Указатели на одномерные массивы в качестве параметров

Функция max_vect формирует массив z, каждый элемент которого равен максимальному из соответствующих значений двух других массивов параметров (x и y). Одномерные массивы передаются в функцию через указатели.

#include <stdio.h>

void max_vect(int, int*, int*, int*);

main()

{

int a[]={1, 2, 3, 4, 5, 6, 7};

int b[]={7, 6, 5, 4, 3, 2, 1};

int c[7];

max_vect(7, a, b, c);

for (int i=0; i<7; i++)

printf("%d\t",c[i]);

}

void max_vect(int n, int *x, int *y, int *z)

{

for (int i=0; i<n; i++)

// z[i]=x[i]>y[i] ? x[i] : y[i];

  *(z+i)=*(x+i)>*(y+i) ? *(x+i) : *(y+i);

Пример 4. Функция возвращает указатель на массив

Функция fussion формирует массив h из двух целочисленных упорядоченных по не убыванию массивов с и d. Массив h должен включать все элементы двух исходных массивов таким образом, чтобы они оказались упорядоченными по неубыванию.

#include <stdio.h>

#include <stdlib.h>

int *fusion(int, int*, int, int*);

void main()

{

int c[]={1, 3, 5, 7, 9};

 int d[]={0, 2, 4, 5};

int *h;     // указатель для массива с результатом

int kc=sizeof(c)/sizeof(c[0]);  // количество элементов в c[0]

int kd=sizeof(d)/sizeof(d[0]);  // количество элементов в d[0]

 h=fusion(kc, c, kd, d);

 puts("\nРезультат объединения массивов: \n");

 for (int i=0; i<kc+kd; i++)

 printf("%3d", h[i]);

//  delete[] h;     // освобождение памяти

 free((void*)h);

}

// функция слияния двух упорядоченных массивов

int *fusion(int n, int* a, int m, int* b)

{

//int *x=new int[n+m]; // захватываем память

 int *x=(int*)malloc((n+m)*sizeof(int));

 int ia=0, ib=0, ix=0;

 while (ia<n && ib<m) // цикл до конца одного из массивов

  if (a[ia]>b[ib]) x[ix++]=b[ib++];

    else x[ix++]=a[ia++];

 if(ia>=n)   //массив a[] исчерпан

   while (ib<m) x[ix++]=b[ib++];

  else            //массив b[] исчерпан

   while (ia<n) x[ix++]=a[ia++];

 return x;

}

Пример 5. Функции работают с двумерными массивами. Память под массив получаем динамически.

//Найти минимальный элемент каждой строки квадратной матрицы,

//лежащий ниже главной диагонали (включая главную).

#include<stdio.h>

#include<stdlib.h>

void in_mas(int*p, int n, int m);                     //ввод массива

void out_mas(int*p, int n, int m);        //вывод массива

int min_mas(int*p, int n, int m, int k);  //нахождение минимума

void main(void)

{  int*p, i, min, N, M;

 puts("Введите размер двухмерного массива");

 scanf("%d%d", &N, &M);

p=(int*)malloc(N*M*sizeof(int));

in_mas(p,N,M);

out_mas(p,N,M);

printf("\n\n");

 //находим минимум для каждой строки

 for(i=0;i<N;i++)

{

 min=min_mas(p,N,M,i);

 printf("min=%d\n",min);

 }

free((void*)p);

}

 void in_mas(int*p,int n,int m)

{

  int i,j;

  randomize();

  for(i=0;i<n;i++)

   for (j=0;j<m;j++)

    *(p+i*m+j)=random(11)-5;

}

 

void out_mas(int*p,int n,int m)

{

  int i,j;

  for(i=0;i<n;i++)

  {

   printf("\n");

   for(j=0;j<m;j++)

    printf("%3d",*(p+i*m+j));

  }

}

int min_mas(int*p, int n, int m, int k)

{

 int min,j;

 min=*(p+k*m);  //переход на 1 элемент нужной строки

   for(j=0; j<m; j++)

  {

   if(j<=k) //условие ниже главной диагонали

    if(*(p+k*m+j)<min)

     min=*(p+k*m+j);

 }

return min;

}

Пример 6. Память под массив захватывается в функции.

Найти сумму элементов, лежащих на главной диагонали.

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

#define M 5

#define N 5

int* vvod(int, int);  //заполнение матрицы случайными числами

void out (int*,int ,int ); //вывод матрицы

int kol_z(int*,int ,int ); //сумма элементов главной диагонали

void main(void)

{

 int* p;

 int s=0;

 p=vvod(N, M);

 puts("\nИсходный массив:");

 out(p, N, M);

 s=kol_z(p,M,N);

 printf("\ns=%d\n",s);

 free((void*)p);

}

//заполнение матрицы случайными числами

int* vvod(int aN, int aM)

{

int*pp;

int i, j;

randomize();

 pp=(int*)malloc(aN*aM*sizeof(int));  //захватываем память

 for(i=0;i<aN;i++)

   for(j=0;j<aM;j++)

      *(pp+i*aM+j)=random(10);

 return pp;

 }

//вывод матрицы

 void out(int *pp,int aN, int aM)

{

 int i,j;

  for(i=0;i<aN;i++)

   {

    printf("\n");

     for(j=0;j<aM;j++)

      printf("%3d",*(pp+i*aM+j));

  }

}

//сумма элементов главной диагонали

int kol_z(int*pp,int aN ,int aM)

  {

   int i, j, ss=0;

   for(i=0;i<aN;i++)

    for(j=0;j<aM;j++)

 if(i==j) ss+=*(pp+i*aM+j);

 return ss;

 }

Классы памяти

В языке Си различают четыре основных класса памяти: внешнюю (глобальную), автоматическую (локальную), статическую и регистровую память.

Внешние (глобальные) переменные определены вне функций и, следовательно, доступны для любой из них. Они могут быть определены только один раз. Выше уже говорилось, что сами функции всегда глобальные. Язык не позволяет определять одни функции внутри других. Область действия внешней переменной простирается от точки во входном файле, где она объявлена, до конца файла. Если на внешнюю переменную нужно ссылаться до ее определения или она определена в другом входном файле, то в подпрограмме или файле она должна быть объявлена как extern.   

Например:

    extern int a; /* Объявление a; память под переменную не

                            резервируется */

Автоматические переменные по отношению к функциям являются внутренними или локальными. Они начинают существовать при входе в функцию и уничтожаются при выходе из нее (для них можно использовать ключевое слово auto). Однако оно практически не используется, так как при отсутствии ключевого слова переменные по умолчанию принадлежат к классу auto.

Статические переменные объявляются с помощью ключевого слова static. Они могут быть внутренними (локальными) или внешними (глобальными). Внутренние статические переменные, как и автоматические, локальны по отношению к отдельной функции. Однако они продолжают существовать, а не возникают и не уничтожаются при каждом ее вызове. Другими словами, они являются собственной постоянной памятью для функции. Внешние статические переменные доступны внутри оставшейся части файла после того, как они в нем объявлены, однако в других файлах они неизвестны. Это, в частности, позволяет скрыть данные одного файла от другого файла.

Регистровые переменные относятся к последнему классу. Ключевое слово register говорит о том, что переменная, о которой идет речь, будет интенсивно использоваться. Если возможно, значения таких переменных помещаются во внутренние регистры микропроцессора, что может привести к более быстрой и короткой программе (разработчики компиляторов фирмы Borland утверждают, что оптимизация компиляторов данной фирмы по использованию регистровых переменных сделана так хорошо, что указание использовать переменную как регистровую может только ухудшить эффективность создаваемого машинного кода). Для регистровых переменных нельзя взять адрес; они могут быть только автоматическими с допустимыми типами int или char.

Таким образом, можно выделить четыре модификатора класса памяти: extern, auto, static, register. Они используются в следующей общей форме:

    модификатор_класса_памяти тип список_переменных;

Выше уже говорилось об инициализации, т.е. о присвоении различным объектам начальных значений. Если явная инициализация отсутствует, гарантируется, что внешние и статические переменные будут иметь значение нуль, а автоматические и регистровые - неопределенное значение.

Пример7. Программа подсчитывает число символов и слов во вводимых строках (пробелы входят в число введенных символов).

#include <stdio.h>

#include <conio.h>

#define ESC 27                /* 27 - ASCII-код клавиши ESC */  

void CountOfLines(void)

{

/* Статические переменные будут сохранять старые значения при каждом

новом вызове функции CountOfLines */

   static int words = 0, symbols = 0; /* words-число слов,

                                         symbols-число символов */

   char temp, t = 0;                  /* Временные переменные */

   ++symbols;

/* Число символов и слов выдается после нажатия клавиши <Enter> */

   while ((temp = getche( )) != '\r' )

   {

       ++symbols;            /* Подсчитывается каждый символ */

/* После одного или нескольких пробелов подсчитывается слово */

       if ((temp == ' ') && (t == 1)) continue;

       if (temp == ' ') { t = 1; ++words; }

       else t = 0;

   }

   if (t == 1) --words;  

   else ++words;

   printf ("\n Слов: %d; символов: %d\n", words, symbols);

}

void main(void)

{

   puts("Для завершения программы нажмите <ESC> в начале строки");

   puts("Строка не должна начинаться с пробела и с нажатия клавиши"

        "<Enter>");

   puts("Строка не должна завершаться пробелом");

   while (getche( ) != ESC) CountOfLines();

   putch('\b');

   putch(' ');

   putch('\b');

}

Результаты работы этой программы:

Для завершения программы нажмите <ESC> в начале строки

Строка не должна начинаться с пробела и с нажатия клавиши <Enter>

Строка не должна завершаться пробелом

Mouse Keyboard <Enter>

Слов: 2  символов: 14

<ESC>

Указатели на функции

В языке Си сама функция не может быть значением переменной, но можно определить указатель на функцию. С ним уже можно обращаться как с переменной: передавать его другим функциям, помещать в массивы и т.п.

Код функции в персональном компьютере занимает физическую память. В этой памяти есть точка входа, которая используется для того, чтобы войти в функцию и запустить ее на выполнение. Указатель на функцию как раз и адресует эту точку входа. Это уже будет обычная переменная и с ней можно делать все, что можно делать с переменной.

Через указатель можно войти в функцию, т.е. запустить ее на выполнение. Объявление вида:

    int (*f)( );

говорит о том, что f - это указатель на функцию, возвращающую целое значение. Первая пара скобок необходима, без них int *f( ); означало бы, что f - функция, возвращающая указатель на целое значение. После объявления указателя на функцию в программе можно использовать объекты: *f - сама функция; f - указатель на функцию. Для любой функции ее имя (без скобок и аргументов) является указателем на эту функцию.

Аргументы функции main( )

В программы на языке Си можно передавать некоторые аргументы. Когда вначале вычислений производится обращение к main( ), ей передаются три параметра. Первый из них определяет число командных аргументов при обращении к программе. Второй представляет собой массив указателей на символьные строки, содержащие эти аргументы (в одной строке - один аргумент). Третий тоже является массивом указателей на символьные строки, он используется для доступа к параметрам операционной системы (к переменным окружения).

Любая такая строка представляется в виде:

    переменная = значение\0

Последнюю строку можно найти по двум заключительным нулям.

Назовем аргументы функции main( ) соответственно: argc, argv и env (возможны и любые другие имена). Тогда допустимы следующие описания:

    main( )

    main(int argc)

    main(int argc, char *argv[ ] )

    main(int argc, char *argv[ ], char *env[ ] )

Предположим, что на диске A: есть некоторая программа prog.exe. Обратимся к ней следующим образом:

    A:\>prog.exe file1 file2 file3 <Enter>

Тогда argv[0] - это указатель на строку A:\prog.exe, argv[1] - на строку file1 и т.д. На первый фактический аргумент указывает argv[1], а на последний - argv[3]. Если argc=1, то после имени программы в командной строке параметров нет. В нашем примере argc=4.

Библиотечные функции

В системах программирования подпрограммы для решения часто встречающихся задач объединяются в библиотеки. К числу таких задач относятся: вычисление математических функций, ввод/вывод данных, обработка строк, взаимодействие со средствами операционной системы и др. Использование библиотечных подпрограмм избавляет пользователя от необходимости разработки соответствующих средств и предоставляет ему дополнительный сервис. Включенные в библиотеки функции на языке Си поставляются вместе с системой программирования. Их объявления даны в файлах *.h (это так называемые включаемые или заголовочные файлы). Поэтому, как уже упоминалось выше, в начале программы с библиотечными функциями должны быть строки вида:

    #include <включаемый_файл_типа_h>

Например:

    #include <condio.h>

Существуют также средства для расширения и создания новых библиотек с программами пользователя.

Рекурсия

Рекурсией называется такой способ вызова, при котором функция обращается к самой себе.

Важным моментом при составлении рекурсивной программы является организация выхода. Здесь легко допустить ошибку, заключающуюся в том, что функция будет последовательно вызывать саму себя бесконечно долго. Поэтому рекурсивный процесс должен шаг за шагом так упрощать задачу, чтобы в конце концов для нее появилось нерекурсивное решение. Использование рекурсии не всегда желательно, так как это может привести к переполнению стека.

Пример 8. Программа демонстрирует использование рекурсивной функции для вычисления факториала. Отметим, что определение функции factorial( ) может находиться и после функции main( ), но в этом случае функция factorial( ) должна быть объявлена перед функцией main( ), т.е. до main( ) необходимо поместить строку: long factorial(int);

#include <stdio.h>

#include <values.h>

#include <process.h>

long factorial(int value)         /* Рекурсивная функция */

{

   long result = 1;

   if (value != 0)

   {

       result = factorial(value - 1);

     /* Проверка возможности вычисления факториала */

       if (result > MAXLONG / (value + 1))

       {

           fprintf(stderr, "Очень большое число\n");

           getch( );             /* Ожидание нажатия клавиши */

           exit (1);

       }

       result *= value;

   }

   return(result);

}

/* Рекурсивное вычисление факториала числа value */

void main(void)

{

   int value;             /* Факториал этого значения вычисляется */

   long result;           /* Переменная для результата */

   puts("Факториал какого числа?");

   scanf("%d", &value);

   result = factorial(value);

   printf("Результат: %ld\n", result);

   getch( );              /* Ожидание нажатия клавиши */

}

Результаты работы этой программы:

Факториал какого числа? 10<Enter>

Результат: 362880


 

А также другие работы, которые могут Вас заинтересовать

22844. Визначення коефіцієнта в’язкості газу 1.32 MB
  При ламінарній течії газу по капілярній трубці різні шари газу набувають різної швидкості направленого руху. Розглянемо більш детально течію вязкого газу по трубці радіуса . Припустимо що потік ламінарний що газ при невеликих тисках нестисливий що течія всановилась і що газ повністю змочує стінки трубки тобто швидкість газу біля стінок трубки дорівнює нулеві.
22845. Визначення вологості повітря 1.2 MB
  Атмосферне повітря має в своєму складі деяку кількість водяної пари що обумовлює вологість повітря. Абсолютною вологістю називається кількість водяної пари що знаходиться в одиниці об'єму повітря. З рівняння стану ідеального газу густину повітря при нормальних умовах можна представити так: пов= 1 позначення загально прийняті.
22846. Визначення коефіцієнта об’ємного розширення рідини 545 KB
  Залежність обєму рідини від температури виражається рівнянням: а при невеликій точності можна обмежитися виразом: де обєм рідини при температурі 0C температурний коефіцієнт обємного розширення рідини. Прямим способом вимірювати обєм рідини при різних температурах для визначення важко бо при цьому змінюється і обєм посудини в якій знаходиться рідина. Французькі вчені Дюлонг і Пті запропонували спосіб визначення коефіцієнта обємного розширення рідини при якому відпадає необхідність вимірювання обєму рідини.
22847. ОДЕРЖАННЯ І ВИМІРЮВАННЯ ВИСОКОГО ВАКУУМУ 5.3 MB
  Різного роду вакуумні насоси з застосуванням деяких додаткових прийомів дозволяють одержувати тиски домм. Області тисків в яких найбільш раціонально застосовуються вакуумні насоси прийнятих в даний час типів показані на рис. Вакуумні насоси що застосовуються для відкачки газу поділяють на два класи: а форвакуумні насоси які починають працювати з атмосферного тиску і викидають відкачуваний газ прямо в атмосферу. Форвакуумні насоси створюють розрідження порядку мм.
22848. ТЕПЛОВЕ РОЗШИРЕННЯ ТВЕРДОГО ТІЛА 340.5 KB
  Дійсно сили що тримають атоми у вузлах ґратки малі і тому достатньо вже теплової енергії самих атомів аби змістити їх з положення рівноваги. До поняття про коливання атомів твердого тіла можна дійти шляхом аналізу природи міжатомних сил. Положення рівноваги атомів визначається з умови рівності сил притягання і відштовхування діючих на атом. Якщо змінюється відстань тільки відносно одного з атомів то енергію Wx треба...
22849. ВИЗНАЧЕННЯ СЕРЕДНЬОГО ЗНАЧЕННЯ ТЕПЛОТИ ВИПАРОВУВАННЯ РІДИНИ 120 KB
  ВИЗНАЧЕННЯ СЕРЕДНЬОГО ЗНАЧЕННЯ ТЕПЛОТИ ВИПАРОВУВАННЯ РІДИНИ. Випаровування це процес зміни агрегатного стану речовини перехід речовини із конденсованого стану в газоподібний. Кількість теплоти яку необхідно надати рідині при ізотермічному утворенні одиниці маси пари називають теплотою випаровування. Для визначення середнього значення теплоти випаровування води в даній роботі використовується метод який грунтується на використанні рівняння КлапейронаКлаузіуса.
22850. ВИЗНАЧЕННЯ КОЕФІЦІЄНТУ ТЕПЛОПРОВІДНОСТІ ПОВІТРЯ 182 KB
  Через довiльну коаксiальну поверхню радiуса y за одиницю часу пройде кiлькiсть теплоти 5 де l довжина дротини.Розділивши в виразі 5 змінні одержимо 6 де внутрішній радiус трубки температура дослiджуваного газу повiтря бiля внутрішньої поверхнi трубки а радiус дротини температура дротини. Зі співвідношення 6 випливає що 7 Таким чином для визначення коефіцієнта теплопровідності треба знати кiлькiсть теплоти яка щосекунди...
22851. ВИЗНАЧЕННЯ КОЕФІЦІЄНТА ТЕПЛОПРОВІДНОСТІ ТВЕРДИХ ТІЛ 111 KB
  Кількість теплоти Q що переноситься через поверхню площею S за час при градієнті температур визначається як: 1 де коефіцієнт теплопровідності середовища. Таким чином значення коефіцієнта теплопровідності матеріалу можна знайти безпосередньо якщо користуватись формулою 1. для визначення коефіцієнта теплопровідності твердих тіл.
22852. ПОБУДОВА ДІАГРАМИ СТАНУ СПЛАВІВ 49 KB
  Сплавом називають систему в твердому стані яку отримують сплавленням двох або більшої кількості компонент. Діаграми стану сплавів характеризують залежність температур фазових переходів зокрема плавлення і кристалізації від концентрації сплаву. Евтектика характеризується сталою температурою плавлення яка нижче температури плавлення компонент. Інтерметалічна сполука характеризується сталою температурою плавлення яка як правило вища за температуру плавлення компонент AuZn CdMg та ін.