Ir ao conteúdo

Posts recomendados

Postado

Boa tarde! Estou iniciando em programação em linguagem c e vi um tipo de argumento para uma função que até então eu não conhecia e fiquei perdido. Segue abaixo a forma da função.

void funcao_arg_void(void (*ptr_sel1) (void), void (*ptr_sel2) (void))
{
  [...]
  
  
}

Esses dois parâmetros que a função recebe são ponteiros para outras funções com os argumentos void? Ou seriam variáveis? Em linguagem c é possível fazer uma variável "Genérica", ou seja,  que aceite qualquer tipo de dado? 

 

desde já, grato.

Postado

Primeiro este código poderia ser escrito assim:

 

void funcao_arg_void(void (*ptr_sel1)(), void (*ptr_sel2)())
{
}

o void que foi retirado apenas indica que o ponteiro da função é uma função que não recebe parâmetros. Muitas vezes as pessoas colocam void entre os parenteses para indicar que a função não recebe paramentros.

 

int main(void)
{
	return 0;
}

E você também pode passar uma variável genérica. Existe um caso pratico, precisamos de uma função de ordenação de arrays, mas você não quer implementar uma função para cada tipo de dados, a linguagem C tem uma implementação generica pra isso chamada qsort. Segue um exemplo de uso da função qsort que está disponivel no header stdlib.h, segue o programa:

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int int_cmp(const void* p1, const void* p2)
{
    int x1 = *(int*)p1;
    int x2 = *(int*)p2;
    if (x1 > x2)
        return 1;
    if (x1 < x2)
        return -1;
    return 0;
}

int double_cmp(const void* p1, const void* p2)
{
    double x1 = *(double*)p1;
    double x2 = *(double*)p2;
    if (x1 > x2)
        return 1;
    if (x1 < x2)
        return -1;
    return 0;
}

int void_strcmp(const void* p1, const void* p2)
{
    // Sim, para ordenar do menos ao maior,
    // pegue o resultado do strcmp e troque o sinal
    return -strcmp(p1, p2);
}

int main()
{
    int vet[4] = { 4, 3, 2, 1};
    qsort(vet, 4, sizeof(int), int_cmp);
    // vet[4] = { 1, 2, 3, 4 }

    double vetd[4] = { 4.1, 5.1, 2.1, 1.1 };
    qsort(vetd, 4, sizeof(double), double_cmp);
    // vetd[4] = { 1.1, 2.1, 4.1, 5.1 }

    char* vetstr[3] = { "silvia", "pedro", "matheus" };
    qsort(vetstr, 3, sizeof(char*), void_strcmp);

    return 0;
}

A função qsort recebe como parametros:

  1. o endereço do primeiro elemento.
  2. a quantidade de elementos.
  3. o tamanho do elemento.
  4. Um ponteiro de função que returna um inteiro, e dois parâmetros const void*

 

 

 

 

 

  • Obrigado 1
Postado

"Esses dois parâmetros que a função recebe são ponteiros para outras funções com os argumentos void?"

Sim.

"Em linguagem c é possível fazer uma variável "Genérica", ou seja,  que aceite qualquer tipo de dado?"

Sim, tipo "void *".

 

  • Curtir 3
Postado

Exemplo de ponteiro void (void *):

#include <stdio.h>

int main()
{
    int a;
    void *b;
    
    a = 5;
    b = &a; //Consegue apontar para qualquer outro tipo (nesse caso é int)
    printf("%d\n", *(int *)b);
    
    
    /*
    
    *b = 7; //Erro! Não dá pra derreferenciar um ponteiro void.
    
    */

    *(int *)b = 6; //Precisa converter para ponteiro de outro tipo para conseguir acessar.
    printf("%d\n", *(int *)b);
    
    return 0;
}

 

 

E já que está falando sobre "usar tipos diferentes de dados na mesma variável", também de uma estudada sobre uniões (union) na linguagem C:

union dados {
  int i;
  float f;
  short s;
  char c;
}

 

  • Obrigado 1
Postado
void funcao_arg_void(void (*ptr_sel1) (void), void (*ptr_sel2) (void))
{
  [...]
}

Você deve ler isso a partir da variável. E assim vai achar mais fácil. 

 

Está claro aí que a função funcao_arg_void() retorna void e recebe dois argumentos, esses separados por ','


Eles são ptr_sel1 e ptr_sel2

 

Vendo o primeiro caso: void (*prt_sel1)(void)

 

você deve ler sempre da direita para a esquerda.

  • assim você tem o parenteses ')' e então é uma função.
  • você tem void então é uma função que não tem argumentos
  • você tem o esperado '(' que define a lista de argumentos da função, (void)
  • você tem um novo ')' e isso vai mudar a prioridade do que você está avaliando. Como numa expressão a * (b + c) em que você tem que somar b e c primeiro para depois multiplicar o total por a.
    dentro do parenteses está o seu argumento, prt_sel1 com um * na frente. O * indica que ptr_sel1 é um ponteiro para algo de um tipo. ptr_sel1 não de um tipo diretamente, assim como int* p indica que p é do tipo int*, um ponteiro para um int.  

    E assim você conclui que ptr_sel1 é um ponteiro para uma função não tem argumentos e que retorna void

Exemplos para funcao_arg_void()

 

#include "stdio.h"

void funcao_a() { return; };
void funcao_b() { return; };
void funcao_c() { return; };
void funcao_d() { return; };

void funcao_arg_void(void (*)(), void (*)());

int main(int argc, char** argv)
{
	funcao_arg_void(funcao_a, funcao_a);
	funcao_arg_void(funcao_a, funcao_b);
	funcao_arg_void(funcao_b, funcao_b);
	funcao_arg_void(funcao_c, NULL);
	return 0;
};	// main()

void funcao_arg_void(void (*ptr_sel1) (void), void (*ptr_sel2) (void))
{
	return;
};

Declarei um protótipo para funcao_arg_void() só para você ver como se costuma declarar isso na prática e não se surpreender se ver isso num livro. Apenas leia da direita para a esquerda e estará bem. No protótipo o asterisco é a pista.

 

Exemplo de uma função com argumentos

 

imagine que você queira passar como parâmetro o endereço de uma entre várias funções que recebem um ponteiro para int e dois char e retornam um char

 

Algo assim

 

char    funcao_a( int*, char, char);

char    funcao_a( int*, char, char);

char    funcao_a( int*, char, char);


você declararia então por exemplo, editando o programa aí de cima
 

#include "stdio.h"

int funcao_a(int* a,char b,char c) { return -34; };
void funcao_v() { return; };
int funcao_arg_void(void (*)(), int (*)(int*, char, char));

int main(int argc, char** argv)
{
	int n = funcao_arg_void(funcao_v, funcao_a);
	printf("funcao retornou %d\n", n);
	return 0;
};	// main()

int funcao_arg_void(void (*ptr_sel1) (void), int (*f) (int*,char,char))
{
	int* a = 0;
	char b = 0; 
	char c = 0;
	ptr_sel1();
	return f(a,b,c);
};

que mostraria claro

 

funcao retornou -34

 

6 horas atrás, Beginner Developer disse:

Em linguagem c é possível fazer uma variável "Genérica", ou seja,  que aceite qualquer tipo de dado

 

 

Não. Formalmente não. C e C++ e linguagens desse tipo são conhecidas como strongly typed e você não há essa possibilidade.

 

2 horas atrás, Flávio Pedroza disse:

Sim, tipo "void *".

 

Não. void* é um tipo muito bem definido. Um ponteiro, com comprimento e semântica bem definidos.

 

No entanto como você pode definir ponteiros e pode alocar memória em bytes na prática pode apontar um ponteiro para qualquer coisa e acaba conseguindo esse efeito.

Coisas como

	void* p = NULL;
	int  i = 8;
	p = (int*)&i;
	printf("Valor apontado por p: %d\n", *(int*)p);

são perfeitamente legais e razão de amor e ódio de especialistas em relação à linguagem C. Mostraria isso

Valor apontado por p: 8


Note por outro lado que nessa estrutura

union dados {
  int i;
  float f;
  short s;
  char c;
}

do exemplo de @isrnick acima, as variáveis tem comprimento diferente então tem essa cara genérica que você pode querer, e sem usar um ponteiro, que é uma variável de tamanho fixo

variant records, uma alternativa dessas, é um uso muito comum desse tipo de estrutura, onde você tem uma estrutura que tem um prefixo comum, e uma "union" no final. No fundo os pacotes de rede por exemplo são todos assim, com um header de tamanho fixo e uma mensagem acoplada. E o header identifica o tipo de mensagem que segue...

 

 

  • Obrigado 1
Postado
6 horas atrás, Beginner Developer disse:

Em linguagem c é possível fazer uma variável "Genérica", ou seja,  que aceite qualquer tipo de dado?

Não existe variável genérica, somente ponteiro genérico.

 

char   caractere_inteiro;
double numero_flutuante;
void   qualquer_coisa; // <-- Não é Possível !!!

Indentação com espaços extras não recomendado.

Postado
3 minutos atrás, Mauro Britivaldo disse:

Não existe variável genérica, somente ponteiro genérico

 

Não, o ponteiro não é genérico. Ele aponta para algo. Mesmo void é algo. Só que não tem *void, então quando ele apontar para algo que você precisa dereferenciar vai precisar de uma conversão. Criar outro ponteiro. Vai ser criada dinamicamente uma maneira dele apontar para essa outra coisa. Ele vai ser convertido para outro ponteiro.
Veja o exemplo que mostrei acima.

 

E esse

	void* p = NULL;
	int  i = 8;
	p = (int*)&i;
	printf("Valor apontado por p: %d\n", *(int*)p);
	p = &i; // ok
	printf("p aponta para %X. Mas o que tem la?\n", p);
	printf("tem %d mas precisa converter o ponteiro...\n", *(int*)p);

Ele é genérico específico :Dsó pode ir para outro void ou deve ser convertido. então não é assim genérico... E aceita ponteiros de outros valores mas é um buraco negro a menos de outra conversão. Pelos exemplos acho que dá pra entender.

 

 

  • Confuso 1
Postado
7 minutos atrás, arfneto disse:

Não, o ponteiro não é genérico.

Quem mais além de você pensa assim! Eu li seus argumentos e estão confusos. Talvez outra pessoa explique melhor. Por enquanto continuo com o que aceito de melhor. Obrigado e irei registra suas ideias para discussões futuras.

Postado
1 hora atrás, isrnick disse:

Por que está dando cast para int* aqui @arfneto ?

&i já aponta para um int

 

Porque é justamente o que estou tentando mostrar. Formalmente (void*) é um buraco negro. Para poder levar a algum lugar está inplícita uma conversão para o tipo do destino, como essa aí. E não existe *void. Imagino que tenha lido os exemplos.

adicionado 8 minutos depois
1 hora atrás, Mauro Britivaldo disse:

Quem mais além de você pensa assim! Eu li seus argumentos e estão confusos

 

Rodou os exemplos que eu mostrei?

Não é minha opinião ou meu argumento. É assim apenas. Não existe *void. Então void não é algo genérico nem em C e muito menos em C++. (void*) é algo criado para facilitar o transporte de ponteiros em argumentos --- syntatic sugar na literatura --- e você pode programar toda a vida sem isso. Mas se programa com isso sabe que a menos de um typecast, como eu expliquei, você não tira nada de um void*. 

 

O que está confuso? 

 

Veja em C++ por exemplo: malloc() retorna void* mas você precisa de um cast para converter o valor retornado ou seu programa sequer compila. 

 

 

Postado
14 horas atrás, arfneto disse:

O que está confuso? 

Dizer que "não é genérico", depois dizer que é "genérico específico",  não muda a ideia que se tem do "Ponteiro Genérico", pelo contrário, o que se tem de explicação para Ponteiro Genérico é isso aí mesmo.

 

14 horas atrás, arfneto disse:

Veja em C++ por exemplo: malloc() retorna void* mas você precisa de um cast para converter o valor retornado ou seu programa sequer compila. 

C++ não é bom exemplo, tem pessoas importantes que pensam o mesmo.

 

Enfim, genérico específico não é bom, mas respeito seu raciocínio até mesmo sua conclusão confusa. 

Postado
17 horas atrás, arfneto disse:

Você deve ler isso a partir da variável. E assim vai achar mais fácil. 

Entendi, mas dessa forma eu posso realizar alguma operação igual eu faço com variáveis? Algo dessa forma: 

Citação

 


void funcao_arg_void(void (*ptr_sel1) (void), void (*ptr_sel2) (void))
{
  // Nesse caso eu estaria verificando o retorno da função ou comparando se a mesma é igual a NULL?
  if(!(void (*ptr_sel1)() || !(void) (*ptr_sel2) ()) 
  {
    
    [ ... ]
  
  }else{
    
    [ ... ]
    
  }
}

 

@Mauro Britivaldo Ou isso não é possível?

Postado
1 hora atrás, Mauro Britivaldo disse:

C++ não é bom exemplo, tem pessoas importantes que pensam o mesmo

 

?? Quem são essas pessoas importantes?
 

Que quer dizer com isso? C e C++ são linguagens importantes em qualquer cenário. Em software embarcado por exemplo quase não há opção. Em games também não. Windows Linux MacOS e Android são todos escritos em C e C++.

 

Poste alguma linha de código que contradiga o que eu expliquei. Não é minha opinião.

  • Formalmente (void*) é um buraco negro. Para poder levar a algum lugar está implícita uma conversão para o tipo do destino, como essa aí nos exemplos que postei. E não existe *void. Imagino que tenha lido os exemplos e que saiba disso
     
  • (void*) é algo criado para facilitar o transporte de ponteiros em argumentos --- syntactic sugar na literatura --- e você pode programar toda a vida sem isso. Mas se programa com isso sabe que a menos de um typecast, como eu expliquei, você não tira nada de um void*

    Veja o exemplo:
    void* p = NULL;
	int  i = 8;
	p = (int*)&i;
	printf("Valor apontado por p: %d\n", *(int*)p);
	p = &i; // ok
	printf("p aponta para %X. Mas o que tem la?\n", p);
	printf("tem %d mas precisa converter o ponteiro...\n", *(int*)p);

Talvez só queira mesmo polemizar.

 

1 hora atrás, Mauro Britivaldo disse:

Enfim, genérico específico não é bom, mas respeito seu raciocínio até mesmo sua conclusão confusa

 

trecho.png.6bfc6bedaece2c990aacfffd881e4c83.png

 

Acho que o emoji não foi suficiente para você entender a ironia, mas podia ter postado o parágrafo todo e algum argumento.

 

Escrevi assim na esperança de que desse para entender que void* é genérico mas só serve pra transporte. Foi criado para isso. C é strongly typed e não há generic programming em C. Como eu disse void* é um buraco negro. O tráfego de variáveis void* só ocorre entre outros void* e não há aritmética de ponteiros nem dereference como sabe: não pode escrever *p para um void* p. Para poder tirar algo delas você precisa de um typecast. Precisa converter para algum tipo. 

 

1 hora atrás, Mauro Britivaldo disse:

respeito seu raciocínio até mesmo sua conclusão confusa

 

Não é "meu raciocínio". É a definição da linguagem:

  • não há artimética de ponteiros void
  • não existe void*
  • não se pode extrair nada que uma área apontada por void a menos de um typecast

 E julgar uma explicação confusa sendo árbitro do que você mesmo não entendeu talvez seja simples presunção. É confusa porque você não entendeu ou você não entendeu porque é confusa?

 

Escreva algum código.

adicionado 2 minutos depois
15 minutos atrás, Beginner Developer disse:

Ou isso não é possível?

Talvez prefira esperar pela resposta de @Mauro Britivaldo mas o que escreveu está errado.

 

Direto do exemplo que te mostrei com detalhes

image.png.812bd38cfca9b1b03d052808b16fcabd.png

Postado

@arfneto Desculpa, na hora de citar eu errei o perfil, eu queria perguntar para você mesmo. Entendi que o tipo void não serve para armazenar nada (Ele só pode ser usado para armazenar o endereço de um outro ponteiro), correto?  

Citação

Você deve ler isso a partir da variável. E assim vai achar mais fácil. 

Então em um código eu posso realizar as operações da mesma forma que faço com variáveis? Algo dessa forma:

void funcao_arg_void(void (*ptr_sel1) (void), void (*ptr_sel2) (void))
{
  // Nesse caso eu estaria verificando o retorno da função ou comparando se a mesma é igual a NULL?
  if(!(void (*ptr_sel1)() || !(void) (*ptr_sel2) ()) 
  {
    
    [ ... ]
  
  }else{
    
    [ ... ]
    
  }
}

@arfneto Isso é possível? Onde está o erro?  

Mais uma vez me desculpe, eu queria mencionar você, mas acabei trocando os perfis na hora de mencionar. 

Postado

image.png.01c1ea5e315f56d8b56f5e6fb2d70516.png

 

Não leu isso? é assim que chama: entendeu o f(a,b,c)? É exatamente o que quer fazer. Por isso eu escrevi o exemplo. Para mostrar como usar no caso mais útil...

 

Você não pode usar as funções de seu exemplo porque elas retornam.... nada. são declaradas como retornando void então não pode usar em expressões. Como pode ver nesta folclórica discussão paralela aqui acima void não serve para muito. É apenas um truque sintático.

 

Postado
40 minutos atrás, arfneto disse:

?? Quem são essas pessoas importantes?
 

Que quer dizer com isso?

 

Acho que ele quis dizer que o que o C++ faz não serve de exemplo para explicar comportamento do C, são linguagens distintas, com ideias diferentes, e tratam void* de maneiras diferentes (o fato do retorno de malloc ter que ser convertido com um cast no C++, mas no C não, é um exemplo disso).

 

 

40 minutos atrás, arfneto disse:

C é strongly typed e não há generic programming em C.

 

Você está confundindo strongly typed com statically typed .

C é uma linguagem statically typed .

 

Há vários discussões sobre se certas linguagens são strongly typed ou weakly typed (C é uma que não se chega a uma conclusão), e não há uma definição técnica universalmente aceita do que esses termos significam, então fazer esse tipo de afirmação de que "C é strongly/weakly typed" não diz nada no fim das contas.

 

O que dá pra fazer é usar o termo para comparar 2 linguagens, escrevendo algo do tipo a "linguagem X é mais strongly typed do que a linguagem Y". Nesse tipo de afirmação dá pra chegar em um consenso aceito pela maioria das pessoas.

 

  • Obrigado 1
Postado
39 minutos atrás, Beginner Developer disse:

@arfneto Desculpa, na hora de citar eu errei o perfil, eu queria perguntar para você mesmo. Entendi que o tipo void não serve para armazenar nada (Ele só pode ser usado para armazenar o endereço de um outro ponteiro), correto?  

Então em um código eu posso realizar as operações da mesma forma que faço com variáveis? Algo dessa forma:


void funcao_arg_void(void (*ptr_sel1) (void), void (*ptr_sel2) (void))
{
  // Nesse caso eu estaria verificando o retorno da função ou comparando se a mesma é igual a NULL?
  if(!(void (*ptr_sel1)() || !(void) (*ptr_sel2) ()) 
  {
    
    [ ... ]
  
  }else{
    
    [ ... ]
    
  }
}

@arfneto Isso é possível? Onde está o erro?  

Mais uma vez me desculpe, eu queria mencionar você, mas acabei trocando os perfis na hora de mencionar. 

 

Você não pode fazer isso, os ponteiros de função declarados não tem returno.

Talvez isso leve anos para realmente entender, e saber colocar em pratica, poucos desenvolvedores sabem manipulas ponteiros, pode-se dizer que você entendeu ponteiro de funções e aritmética de ponteiros quando for capaz de implementar a própria função qsort ou bsearch.

Dar exemplos de uso é difícil, segue mais um e veja se é isso que deseja fazer

 

 

#include <stdio.h>
#include <stdbool.h>

bool eh_par(int i)
{
    return (i % 2) == 0;
}

bool eh_impar(int i)
{
    return !eh_par(i);
}

bool eh_n_primo(int target)
{
    if (target < 2 || eh_par(target))
        return false;
    if (target == 2)
        return true;

    for (size_t i = 3; i < target; i += 2)
        if ((target % i == 0))
            return false;

    return true;
}

void display_if(int* arr, size_t size, bool (where)(int))
{
    for (size_t i = 0; i < size; i++)
        if (where(arr[i]))
            printf("%d, ", arr[i]);
}

#define VET_SIZE (20)

int main()
{
    int vet[VET_SIZE];
    for (size_t i = 0; i < VET_SIZE; i++)
        vet[i] = i;

    printf("Pares: ");
    display_if(vet, VET_SIZE, eh_par);
    printf("\b\b \n");

    printf("Impares: ");
    display_if(vet, VET_SIZE, eh_impar);
    printf("\b\b \n");

    printf("Primos: ");
    display_if(vet, VET_SIZE, eh_n_primo);
    printf("\b\b \n");

    return 0;
}

 

note que o ponteiro de função também pode ser declarado sem o *

 

Postado
15 minutos atrás, isrnick disse:

Você está confundindo strongly typed com statically typed .

C é uma linguagem statically typed .

 


O próprio Brian Kernighan disse em uma entrevista recente que C e C++ são "strongly typed languages". Vou achar o vídeo da conferência... Está disponível no YouTube. E no CPPCON '17 acho que o prof. Straustrup, que criou a linguagem, disse que era uma vantagem ela ser... "strongly typed" como C.

 

De todo modo o weak para alguns só poderia estar pelo caso de void* e os typecasts afinal

 

Ou você tem um outro argumento? 
 

Eu vejo C tão strongly typed quando possível, exceto por esses dois aspectos. Não acho no entanto algo importante. Linguagens são coisas formais. E são como são: em cada linguagem o desenvolvedor... desenvolve. 

 

 

  • Membro VIP
Postado

Vou me meter no meio dos tubarões...  rs.

 

Vamos lá:

32 minutos atrás, Matheus Maldi disse:
1 hora atrás, Beginner Developer disse:

@arfneto Desculpa, na hora de citar eu errei o perfil, eu queria perguntar para você mesmo. Entendi que o tipo void não serve para armazenar nada (Ele só pode ser usado para armazenar o endereço de um outro ponteiro), correto?  

Então em um código eu posso realizar as operações da mesma forma que faço com variáveis? Algo dessa forma:



void funcao_arg_void(void (*ptr_sel1) (void), void (*ptr_sel2) (void))
{
  // Nesse caso eu estaria verificando o retorno da função ou comparando se a mesma é igual a NULL?
  if(!(void (*ptr_sel1)() || !(void) (*ptr_sel2) ()) 
  {
    
    [ ... ]
  
  }else{
    
    [ ... ]
    
  }
}

@arfneto Isso é possível? Onde está o erro?  

Mais uma vez me desculpe, eu queria mencionar você, mas acabei trocando os perfis na hora de mencionar. 

 

Você não pode fazer isso, os ponteiros de função declarados não tem returno.

 

Acho que apenas quer utilizar o retorno da função que foi passada por parâmetro!!!

Vide:
 

31 minutos atrás, Matheus Maldi disse:

void display_if(int* arr, size_t size, bool (where)(int))
{
    for (size_t i = 0; i < size; i++)
        if (where(arr[i])) //<--- aqui
            printf("%d, ", arr[i]);
}

 

Certamente eu sou o mais leigo em C daqui, mas pelo que eu consegui supor da estrutura... você está chamando uma função nesta linha destacada e está sim utilizando o retorno da função :D

 

 

@Beginner Developer, não é isso que você quer, não?

 

adicionado 5 minutos depois

 

1 hora atrás, Beginner Developer disse:

  // Nesse caso eu estaria verificando o retorno da função ou comparando se a mesma é igual a NULL?
  if(!(void (*ptr_sel1)() || !(void) (*ptr_sel2) ()) 

 

Ou seria algo assim?
 

Se seria possível passar um null onde deveria passar a função:

    printf("Pares: ");
    display_if(vet, VET_SIZE, Null);
    printf("\b\b \n");

Daí, dentro do display_if, verifica se passou uma função ou não.

 

Postado
3 minutos atrás, Simon Viegas disse:

Acho que apenas quer utilizar o retorno da função que foi passada por parâmetro!!!

 

@Simon Viegas Simon, entenda que uma função void não retorna nada e não pode ser usada em uma expressão. Não é um "rvalue" se diz.

 

Por isso postei inicialmente um exemplo adicional mostrando uma função que retorna algo. E mostrei de novo acima....image.png.71f547e979206f0cabb81d4b49704505.png
 

Aqui pode ver os dois casos...

 Você pode apenas chamar

    ptr_sel1(); 

em funcao_arg_void() mas pode escrever

        c = b + f(a,b,c) * 12;

...

 

Postado

@arfneto Ex:

#include <stdio.h>
#include <limits.h>
int main(void) {
    long long x=LLONG_MAX;
    int y=x;
    printf("x=%lld \ny=%d \n", x, y);
    return 0;
}

A linguagem C faz conversões implícitas de tipo na atribuição, mesmo quando vai de um tipo maior para um menor, como no exemplo acima que um valor maior do que cabe na variável é atribuído a ela, mas não considera isso como um erro.

 

 

E do Wikipedia:

 

image.png.91430b7904fc3b3398f4f7ed1814b1c9.png

 

Ou seja, a presença ou ausência de segurança de tipo, segurança de memória, checagem estática de tipo ou checagem dinâmica de tipo, são comumente usados como evidência de quão strongly typed ou weakly typed uma linguagem é.

 

Mas C não tem segurança de tipo nem segurança de memória.

 

Postado

Seja como diz então. Já expliquei o que eu pretendia para o caso de void* e dei exemplos para o autor do tópico sobre as funções void ou não void passadas como parâmetro para outras função. E postei dois programas que chamam as tais funções. Deve servir. weak or strongly type C could be as a language
 

Algo que talvez não tenha notado sobre o artigo que postou:

 

image.png.3c850db6447306c6e82ac2597e295798.png

 

Está bem. Entenda que Wikipedia é uma enciclopédia coletiva. Note o botão edit lá em cima. E o cara que começa a escrever com algo como "in fact" na Wikipedia já mostra uma tendência como a dos caras que escrevem em lugares como o Quora ou o Discord. Uma certa arrogância, talvez...

E a explicação provável vem logo a seguir:

 

image.thumb.png.8d7f16e3f818d6cd5878e42d52af446c.png

 

Veja o alerta acima: esse próprio artigo que citou é baseado possivelmente em pesquisa original. Esse é um problema comum da WikiPedia em que autores vão lá e editam verbetes de acordo com a própria pesquisa deles. No aviso (de Maio de 2018) tem um link dizendo como remover a mensagem e não basear o artigo em pesquisa original... E isso não foi feito desde então porque a mensagem obviamente está lá em maio de 2020.

 

De todo modo reproduzo a lista de referência com autores importantes e explícitos que está ao final do artigo
 

em https://en.wikipedia.org/wiki/Strong_and_weak_typing

 

image.thumb.png.3bc24afa2920f9ba8739722be832fe71.png

 

  • Curtir 1
Postado

@arfneto Eu afirmei de início que não há uma definição técnica universalmente aceita do que esses termos strongly typedweakly typed significam. E servem mais como um parâmetro de comparação.

 

Você me pediu para indicar outros argumentos que poderiam fazer considerar a linguagem C mais weakly typed (ou menos strongly typed), além do que você mencionou, e eu fiz isso.

 

E sim, obviamente eu sei que a Wikipedia é falha, mas não quer dizer que seja inútil.

 

Não quero dizer que aquelas características mencionados no parágrafo do Wikipedia definam completamente se uma linguagem é ou não strongly/weakly typed, mas podem servir como alguns dos fatores a serem considerados quando se faz esse tipo de avaliação da "força" dos tipos na linguagem.

 

  • Curtir 2
  • Membro VIP
Postado
1 hora atrás, arfneto disse:

@Simon Viegas Simon, entenda que uma função void não retorna nada e não pode ser usada em uma expressão. Não é um "rvalue" se diz.

 

Então, essa parte eu já sabia.. a minha confusão foi na minha interpretação do @Matheus Maldi.

 

2 horas atrás, Matheus Maldi disse:

Você não pode fazer isso, os ponteiros de função declarados não tem returno.

 

Ou seja: eu tinha entendido que quis dizer que "qualquer função não poderia ser utilizada assim".... e como não conhecia (não conheço) esta possibilidade de passar uma função por parâmetro direito, não tinha notado que o teu exemplo também já utiliza o retorno da função que foi passada por parâmetro... 

 

 

 

Ficou então faltando a outra parte da dúvida:

 

1 hora atrás, Simon Viegas disse:

Ou seria algo assim?
 

Se seria possível passar um null onde deveria passar a função:


    printf("Pares: ");
    display_if(vet, VET_SIZE, Null);
    printf("\b\b \n");

Daí, dentro do display_if, verifica se passou uma função ou não.

 

Algo como:

  // Nesse caso eu estaria verificando o retorno da função ou comparando se a mesma é igual a NULL?
  if (!(<a função1 é uma função?>) || !(<a função2 é uma função?>) 
      <faço outra coisa> //ex.: "imprimir um texto na tela dizendo que não chegou uma das função"
  else
      <faço alguma coisa utilizando as funções>

 

Resumindo:

* para utilizar um retorno da função, bastaria configurar qual retorno quer utilizar; OK

* ali no if estaria verificando se é uma função ou não, ou seja: se o ponteiro aponta para uma função ou para null (ou algo do tipo)... e não querendo dizer que quer utilizar o valor de retorno da suposta função em si.

 

  • Curtir 1
Postado
4 horas atrás, arfneto disse:

Quem são essas pessoas importantes?

Agora não lembro, mas isso é apenas um lapso de memoria.

 
4 horas atrás, arfneto disse:

Acho que o emoji não foi suficiente para você entender a ironia, mas podia ter postado o parágrafo todo e algum argumento.

Não foi mesmo e gostaria que não tentasse.

 
4 horas atrás, arfneto disse:

Escrevi assim na esperança de que desse para entender que void* é genérico mas só serve pra transporte. Foi criado para isso [...]

Não há como negar, essa é a citação padrão é suficiente.

  • Haha 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...