Выбрать главу

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

int main() {

// ошибка: директива связывания не может появиться

// внутри тела функции

extern "C" double sqrt( double );

double getValue(); //правильно

double result = sqrt ( getValue() );

//...

return 0;

}

Если мы переместим директиву так, чтобы она оказалась вне тела main(), программа откомпилируется правильно:

extern "C" double sqrt( double );

int main() {

double getValue(); //правильно

double result = sqrt ( getValue() );

//...

return 0;

}

Однако более подходящее место для директивы связывания – заголовочный файл, где находится объявление функции, описывающее ее интерфейс.

Как сделать С++ функцию доступной для программы на С? Директива extern "C" поможет и в этом:

// функция calc() может быть вызвана из программы на C

extern "C" double calc( double dparm ) { /* ... */ }

Если в одном файле имеется несколько объявлений функции, то директива связывания может быть указана при каждом из них или только при первом – в этом случае она распространяется и на все последующие объявления. Например:

// ---- myMath.h ----

extern "C" double calc( double );

// ---- myMath.C ----

// объявление calc() в myMath.h

#include "myMath.h"

// определение функции extern "C" calc()

// функция calc() может быть вызвана из программы на C

double calc( double dparm ) { // ... }

В данном разделе мы видели примеры директивы связывания extern "C" только для языка С. Это единственный внешний язык, поддержку которого гарантирует стандарт С++. Конкретная реализация может поддерживать связь и с другими языками. Например, extern "Ada" для функций, написанных на языке Ada; extern "FORTRAN" для языка FORTRAN и т.д. Мы описали один из случаев использования ключевого слова extern в С++. В разделе 8.2 мы покажем, что это слово имеет и другое назначение в объявлениях функций и объектов.

Упражнение 7.14

exit(), printf(), malloc(), strcpy() и strlen() являются функциями из библиотеки С. Модифицируйте приведенную ниже С-программу так, чтобы она компилировалась и связывалась в С++.

const char *str = "hello";

void *malloc( int );

char *strcpy( char *, const char * );

int printf( const char *, ... );

int exit( int );

int strlen( const char * );

int main()

{ /* программа на языке С */

char* s = malloc( strlen(str)+l );

strcpy( s, str );

printf( "%s, world\n", s );

exit( 0 );

}

7.8. Функция main(): разбор параметров командной строки

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

prog -d -o of lie dataO

Фактические параметры являются аргументами функции main() и могут быть получены из массива C-строк с именем argv; мы покажем, как их использовать.

Во всех предыдущих примерах определение main() содержало пустой список:

int main() { ... }

Развернутая сигнатура main() позволяет получить доступ к параметрам, которые были заданы пользователем в командной строке:

int main( int argc, char *argv[] ){...}

argc содержит их количество, а argv – C-строки, представляющие собой отдельные значения (в командной строке они разделяются пробелами). Скажем, при запуске команды

prog -d -o ofile data0

argc получает значение 5, а argv включает следующие строки:

argv[ 0 ] = "prog";

argv[ 1 ] = "-d";

argv[ 2 ] = "-o";

argv[ 3 ] = "ofile";

argv[ 4 ] = "dataO";

В argv[0] всегда входит имя команды (программы). Элементы с индексами от 1 до argc-1 служат параметрами.

Посмотрим, как можно извлечь и использовать значения, помещенные в argv. Пусть программа из нашего примера вызывается таким образом:

prog [-d] [-h] [-v]

[-o output_file] [-l limit_value]

file_name

[ file_name [file_name [ ... ]]]

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

prog chap1.doc

Но можно запускать и так:

prog -l 1024 -o chap1-2.out chapl.doc chap2.doc

prog d chap3.doc

prog -l 512 -d chap4.doc

При разборе параметров командной строки выполняются следующие основные шаги:

По очереди извлечь каждый параметр из argv. Мы используем для этого цикл for с начальным индексом 1 (пропуская, таким образом, имя программы):

for ( int ix = 1; ix argc; ++ix ) {

char *pchar = argv[ ix ];