Язык С

Указатели - не целые


Вы, возможно, обратили внимание в предыдущих "с"-прог- раммах на довольно непринужденное отношение к копированию указателей. В общем это верно, что на большинстве машин ука- затель можно присвоить целому и передать его обратно, не из- менив его; при этом не происходит никакого масштабирования или преобразования и ни один бит не теряется. к сожалению, это ведет к вольному обращению с функциями, возвращающими указатели, которые затем просто передаются другим функциям, - необходимые описания указателей часто опускаются. Рассмот- рим, например, функцию STRSAVE(S), которая копирует строку S в некоторое место для хранения, выделяемое посредством обра- щения к функции ALLOC, и возвращает указатель на это место. Правильно она должна быть записана так:

CHAR *STRSAVE(S) /* SAVE STRING S SOMEWHERE */ CHAR *S; { CHAR *P, *ALLOC();

IF ((P = ALLOC(STRLEN(S)+1)) != NULL) STRCPY(P, S); RETURN(P); }

на практике существует сильное стремление опускать описания:

*STRSAVE(S) /* SAVE STRING S SOMEWHERE */ { CHAR *P;

IF ((P = ALLOC(STRLEN(S)+1)) != NULL) STRCPY(P, S); RETURN(P); }

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



    Содержание раздела