Jump to content

Funções em C


dimi_hk
Go to solution Solved by rdolxd,

Recommended Posts

dimi_hk

então estou com um pequeno problema sou meio novo no c e estou a estudar funções, o que esta a acontecer é que ele esta sempre a retornar 1 quando eu queria que ele retorna-se 1,0,-1,-2 (etc) usando a função pocoes ou seja o imput final seria 1, 0, -1, -2 (etc) em vez de so 1 infinitamente. O que estarei a fazer mal?

#include<stdio.h>
int pocoes(){

int pocoes = 2;

pocoes --;
printf("\nLifes : %i", pocoes);

}

main(){

while(1){
    pocoes();
 }
 }
Link to post
Share on other sites
  • Solution

A tua variável pocoes está a ser declarada dentro da função e começa sempre por 2, mesmo que chames isso 5000 vezes o que ele vai fazer é, criar a variável pocoes, meter o valor 2 lá dentro e depois subtrair um.

Tens várias formas de fazer isso, em vez de ser uma variável dentro da função, usares uma variável global, em que a metes fora da função e já a consegues mudar sempre que chamas a função pocoes. Podes possivelmente depois brincar um bocado com apontadores e receber um apontador de um inteiro como argumento da função e alteras o valor lá dentro (em C é essencial entender esta mecanica dos apontadores, o que são e como trabalhar com eles).

Na programação existe 1001 formas de fazer tudo e mais alguma coisa, umas melhores que outras ;)

Espero ter conseguido ajudar.

  • Vote 1
Link to post
Share on other sites
dimi_hk
Em 15/01/2021 às 16:53, rdolxd disse:

A tua variável pocoes está a ser declarada dentro da função e começa sempre por 2, mesmo que chames isso 5000 vezes o que ele vai fazer é, criar a variável pocoes, meter o valor 2 lá dentro e depois subtrair um.

Tens várias formas de fazer isso, em vez de ser uma variável dentro da função, usares uma variável global, em que a metes fora da função e já a consegues mudar sempre que chamas a função pocoes. Podes possivelmente depois brincar um bocado com apontadores e receber um apontador de um inteiro como argumento da função e alteras o valor lá dentro (em C é essencial entender esta mecanica dos apontadores, o que são e como trabalhar com eles).

Na programação existe 1001 formas de fazer tudo e mais alguma coisa, umas melhores que outras ;)

Espero ter conseguido ajudar.

Fico muito agradecido e já consegui fazer graças a si fica ai o código que fiz 

#include<stdio.h>

int pocoes2 = 2;

pocoes(){
    pocoes2 --;
    printf("\nLifes : %i", pocoes2);
}

 main(){

for(int i = 0; i < 5; i++){
    pocoes();
    if(pocoes2 == 0){
        return 0;
    }
  }
}
Link to post
Share on other sites
AshKetshup

Olá @dimi_hk.
Fico feliz pelo que alcançaste.
No entanto acredito que pode ser melhorado, portanto aqui vão algumas dicas.

De forma semelhante a como declaras variáveis em C, podemos declarar também funções:
 

// Para declarares uma variavel, repara como tens de indicar primeiro o tipo da mesma,
// por exemplo ao declarar uma variavel como um Inteiro (int).

int variavel; 
// ou
int variavel = 0;

/* De forma semelhante segue a definição de uma função que retorna um tipo segue esta construção:
 * [tipo]      : o tipo da variavel que pretendes retornar no final.
 * [parametros]: os parametros que desejas passar como se os tivesses a definir. 
 *       Neste formato: [tipo] [nome do parametro]
 * 
 * 		[tipo] nomeDaFuncao([parametros]) {
 *			[bloco de comandos]
 *			return [variavel do tipo da função];
 *		}
 * 
 * Segue o exemplo de uma função para somar dois valores inteiros:
 */

int soma(int valor1, int valor2) {
	int total = valor1 + valor2;
  	return total;
}

// esta é a função main (o programa vai começar sempre por esta função)
int main() {
  	int v1 = 3;
  	int v2 = 6;
  
  	// repara que as variaveis que passas como parametros não
  	// precisam de ter o mesmo nome
  	int resultado = soma(v1, v2); 
  	printf("%i + %i = %i", v1, v2, resultado);	
  
  	return 1; // para retornar um inteiro.
}

/*	Notas:
 * 		- Repara como a função tem de estar por cima de onde a chamaste.
 *		- Podes não passar nenhuma variavel como parametro para a função caso a definas sem nada entre os ().	
 *		- Podes não returnar variaveis se usares o void no tipo da função.
 *		
 */

Espero ter conseguido ajudar!

Mas façam o que fizerem nunca façam:

sudo apt remove python

 

Link to post
Share on other sites
thoga31
31 minutos atrás, AshKetshup disse:

portanto aqui vão algumas dicas

Boas dicas! Não obstante, tenho um reparo a fazer.

Só há 2 protótipos da função main() reconhecidos pelos standards mais recentes da linguagem C, sendo eles:

int main(void) { }
int main(int argc, char **argv) { }

É importante referir que funções sem argumentos devem ter explicitado void. Isto deve-se ao facto do gcc (compilador de C da GNU) ser altamente permissivo (e não sei se este comportamento está devidamente documentado no standard, terei de ler). Ou seja, se não indicarmos o void, podemos fazer pérolas destas sem que o gcc se queixe de nada:

int soma() {
   return 42;
}

int main(void) {
   printf("%d\n", soma(2, 3));
   return 0;
}

Ou seja, a função soma() não tem argumentos, mas conseguimos passar dois deles ao chamá-la! Em vez de dar a resposta esperada, 5, irá devolver 42 sempre.

Para que o compilador nos possa avisar e emitir o erro devido, devemos antes fazer o seguinte:

int soma(void) {
   return 42;
}

int main(void) {
   printf("%d\n", soma(2, 3));  // Vai emitir erro aqui
   return 0;
}

Cumprimentos.

  • Vote 1
  • Thanks 1

Knowledge is free!

Link to post
Share on other sites
rbsrbs_dev
Quote

É importante referir que funções sem argumentos devem ter explicitado void. Isto deve-se ao facto do gcc (compilador de C da GNU) ser altamente permissivo (e não sei se este comportamento está devidamente documentado no standard, terei de ler). Ou seja, se não indicarmos o void, podemos fazer pérolas destas sem que o gcc se queixe de nada:

De facto o gcc é permissivo principalmente pelo facto de por default não conformar com nenhum C standard ISO, mas sim outros como o gnu90 ou gnu11 desde a versão 5.1.0.
Especificando flags como `-std=c11 -pedantic` já não se verifica tanto essa permissividade.

Mas neste caso é mesmo o standard que define esta situação como undefined behavior o que por norma os compiladores sem obrigação de reportar nada, compilam com todo o gosto silenciosamente 😄

O problema deve-se dessa definição de função não conter um protótipo válido: aquilo que os compiladores utilizam para verificar a validade dos function calls como quantidade e tipos dos argumentos. 

Esta situação só advém por ainda ser válido em C11 declarar e definir funções no estilo antigo K&R, embora se encontre como "obsolescent feature". Existem intenções de se remover de vez no próximo C23, mas não punha as mãos no fogo por isto.

Os pontos relevantes a descrever a situação dos parâmetros no C11 standard draft são:
 

Quote

§6.5.2.2 Function calls

6 If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not equal the number of parameters, the behavior is undefined. [...]

8 No other conversions are performed implicitly; in particular, the number and types of arguments are not compared with those of the parameters in a function definition that does not include a function prototype declarator.

 

Quote

§6.7.6.3 Function declarators (including prototypes)

3 An identifier list in a function declarator that is not part of a definition of that function shall be empty.

6 A parameter type list specifies the types of, and may declare identifiers for, the parameters of the function.

10 The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.

14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.145)

145) See ‘‘future language directions’’ (6.11.6).

 

Quote

§6.9.1 Function definitions

5 If the declarator includes a parameter type list, the declaration of each parameter shall include an identifier, except for the special case of a parameter list consisting of a single parameter of type void, in which case there shall not be an identifier. No declaration list shall follow.

6 If the declarator includes an identifier list, each declaration in the declaration list shall have at least one declarator, those declarators shall declare only identifiers from the identifier list, and every identifier in the identifier list shall be declared. An identifier declared as a typedef name shall not be redeclared as a parameter. The declarations in the declaration list shall contain no storage-class specifier other than register and no initializations.

7 The declarator in a function definition specifies the name of the function being defined and the identifiers of its parameters. If the declarator includes a parameter type list, the list also specifies the types of all the parameters; such a declarator also serves as a function prototype for later calls to the same function in the same translation unit. If the declarator includes an identifier list,163) the types of the parameters shall be declared in a following declaration list. In either case, the type of each parameter is adjusted as described in 6.7.6.3 for a parameter type list; the resulting type shall be a complete object type.

163) See ‘‘future language directions’’ (6.11.7).

 

Quote

6.11 Future language directions

§6.11.6 Function declarators

1 The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.

§6.11.7 Function definitions

1 The use of function definitions with separate parameter identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.

Na introdução descrevem o que querem dizer com `obsolescent`:

Quote

Introduction

2 Certain features are obsolescent, which means that they may be considered for withdrawal in future revisions of this International Standard. They are retained because of their widespread use, but their use in new implementations (for implementation features) or new programs (for language [6.11] or library features [7.31]) is discouraged.

 

TL;RD:

int
// Function declaration K&R-style
// Not a valid prototype
foo_old();

int
foo_old(a, b); // Invalid by point 3 in §6.7.6.3

int
// Function definition K&R-style
// Not a valid prototype
foo_old(a, b) // <- identifier list
int a; int b; // <- parameter type list
{return a + b;}


int
// Function declaration ANSI/ISO C
// Valid prototype
foo_new(int a, int b); // <- parameter type list

int
// Function declaration ANSI/ISO C
// Valid prototype
foo_new(int, int); // <- parameter type list without identifiers

int
// Function definition ANSI/ISO C
// Valid prototype
foo_new(int a, int b)
{return a + b;}

Para funções que não recebem parâmetros:

int
// Indica que a função pode receber um quantidade não especificado de parâmetros e de tipos não especificados
// K&R-style
foo();

int
// Indica que a função não recebe nenhum parâmetro, mas como não constitui um protótipo válido não faz check
// K&R-style
foo()
{return 42;}

int
// Indica que a função não recebe nenhum parâmetro
// New style
foo(void);

int
// Indica que a função não recebe nenhum parâmetro
// New style
foo(void)
{return 42;}
Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.