Почему эта переменная двойного типа по умолчанию имеет значение int при передаче в качестве параметра функции? - PullRequest
2 голосов
/ 17 апреля 2020

Я учусь C и пытался помочь отладить код друзей. Он определял параметры своей функции в глобальной области видимости и затем передавал их в функцию def следующим образом:

#include <stdio.h>

double x;


double myfunc(x){
    return x;    
}

void main(){

}

Я понял, что это неправильно, но не потому, что возникает следующая ошибка:

main.c:14:8: warning: type of ‘x’ defaults to ‘int’ [-Wimplicit-int] 

Может кто-нибудь помочь мне понять, как компьютер интерпретирует этот код?

Ответы [ 4 ]

6 голосов
/ 17 апреля 2020

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

Нет, он не определяет.

Глобальное значение x не связано к параметру функции x.

Первый является глобальным double, последний является локальным для функции и, как предупреждает компилятор, " по умолчанию равен int ".

Я понял, что это неправильно

Это не так, но невозможно.

1 голос
/ 17 апреля 2020

Глобальная переменная

double x;

не имеет отношения к параметру x из func.

Поскольку тип x не указан, компилятор по умолчанию имеет значение int тип (до C99). Но это предположение неверно, поскольку C99 .

Поэтому либо укажите тип для x (например: double func(double x) { ...}), либо просто не передавайте ему аргументы в все, если вы хотите использовать глобальный x.

Как правило, избегайте глобальных. Или, по крайней мере, сделайте это static, чтобы оно не было видно за пределами блока перевода.

0 голосов
/ 18 апреля 2020

Когда вы пишете:

double myfunc(x){
    return x;    
}

, вы объявляете функцию в устаревшем стиле первого издания книги Kernighan & Ritchies "C Язык программирования".

Это Стиль, все еще живой, позволяет объявлять функцию, просто называя ее параметры (которые всегда локальны для функции , поэтому глобальная x является переменной, отличной от параметра x для функции) и, поскольку вы не указываете его тип, по умолчанию он равен int. Таким образом, вы фактически объявляете (в ANSI- C) следующую функцию:

double myfunc(int x){
    return x;    
}

и, как видите, она принимает целочисленный параметр.

Параметры для функции: ВСЕГДА локально для функции, вы не можете сделать их глобальными переменными.

Примечание:

Если вы хотите определить функцию в старом стиле C, правильное определение будет быть:

double myfunc(x)
    double x;
{
    return x;    
}

в ANSI- C is:

double myfunc(double x)
{
    return x;    
}

Я попытался скомпилировать следующую программу на моем компьютере:

#include <math.h>
#include <stdio.h>

double myFunc(x)
{
        return x;
}

int main()
{
        printf("%g\n", myFunc(M_PI));
}

с помощью следующие ПРЕДУПРЕЖДЕНИЕ :

$ make pru
cc -O2 -pipe  pru33336.c  -o pru33336
pru33336.c:11:24: warning: implicit conversion from 'double' to 'int' changes value from 3.141592653589793 to 3 [-Wliteral-conversion]
        printf("%g\n", myFunc(M_PI));
                       ~~~~~~ ^~~~
/usr/include/math.h:149:15: note: expanded from macro 'M_PI'
#define M_PI            3.14159265358979323846  /* pi */
                        ^~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
$ _

Таким образом, вы можете видеть, что выполняется автоматическое преобразование c для преобразования двойного значения, переданного функции, в int, чтобы соответствовать тип параметра. Если вы запустите программу, вы получите только

$ pru
3
$ _
0 голосов
/ 17 апреля 2020

Ваш друг использует более старый, K & R-стиль определения функций, где типы параметров указываются отдельно от списка параметров. Если все сделано правильно, это будет выглядеть так:

double myfunc(x)
  double x;
{
  return x;
}

Однако лучше использовать синтаксис прототипа, где тип параметра указан с именем параметра:

double myfunc( double x )
{
  return x;
}

Обратите внимание, что этот параметр x не имеет ничего общего с глобальной переменной x - это совершенно отдельный объект.

В более старых версиях C, если функция не имеет возвращаемого типа или если параметр не был объявлен с типом, компилятор предположил, что он имеет тип int. Неявная типизация int была устранена в стандарте IINM 1999 года, и на нее не следует полагаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...