Ir ao conteúdo

Posts recomendados

Postado

Bom dia, queria fazer umas tabelas para listar algumas informações mas não tenho ideia de como fazer, se alguém puder ajudar agradecia.

o código da informação lista por linhas é o seguinte: 

                printf("\nID: %d",atual->id);

                printf("\nNome: %s", atual->nome_cliente);

                printf("\nDescricao: %s",atual->descricao);

                printf("\nMontante total: %.2f", atual->montante_total);

                printf("\nNumero de fontes de rendimento: %d", atual->n_fontes_rendimento);

                printf("\nFontes de Rendimento: ");

                for(int i = 0; i < atual->n_fontes_rendimento; i++){

                    printf("\n%d. %s"

                            "\nDescricao da fonte de rendimento: %s"

                            "\nMontante da fonte de rendimento: %.2f"

                        ,contador,atual->fontes_rendimento[i], atual->descricao_fonte[i], atual->montante_fonte[i]);

                        contador++ ;

                    }

  • Curtir 1
Postado

@jorge.b , bom dia.

 

Veja esse exemplo em Linguagem C.

 

/******************************************************************************
Exibir uma tabela (array[4][4]) utilizando dois laços com for()
Diego Mendes Rodrigues
*******************************************************************************/

#include <stdio.h>

int main()
{
    int valores[4][4] = {
        {1, 4, 29, 20}, 
        {32, 9, 12, 24}, 
        {2, 49, 7, 11},
        {5, 6, 13, 19}
    };
    int linha, coluna;
    
    for(linha=0;linha<4;linha++) {
        for(coluna=0;coluna<4;coluna++) {
            printf("%d ", valores[linha][coluna]);
        }
        printf("\n");
    }

    return 0;
}

 

Link para você testar:

https://onlinegdb.com/cFlAY_3yw

 

Espero ter ajudado!

Abraço,

Diego

  • Curtir 1
  • Obrigado 1
Postado
5 horas atrás, Diego Mendes Rodrigues disse:

@jorge.b , bom dia.

 

Veja esse exemplo em Linguagem C.

 

/******************************************************************************
Exibir uma tabela (array[4][4]) utilizando dois laços com for()
Diego Mendes Rodrigues
*******************************************************************************/

#include <stdio.h>

int main()
{
    int valores[4][4] = {
        {1, 4, 29, 20}, 
        {32, 9, 12, 24}, 
        {2, 49, 7, 11},
        {5, 6, 13, 19}
    };
    int linha, coluna;
    
    for(linha=0;linha<4;linha++) {
        for(coluna=0;coluna<4;coluna++) {
            printf("%d ", valores[linha][coluna]);
        }
        printf("\n");
    }

    return 0;
}

 

Link para você testar:

https://onlinegdb.com/cFlAY_3yw

 

Espero ter ajudado!

Abraço,

Diego

obrigado pela ajuda

 

  • Curtir 1
  • Obrigado 1
Postado

@jorge.b provavelmente teria mais ideias de como fazer começando pelos dados e não pelo programa.

 

Escrever em torno dos dados em geral leva a programas mais simples e certos desde a primeira execução.

 

EXEMPLO

 

Não ficou claro o que quer fazer, mas imaginando algo assim:

 

001-X Kriss um Cliente        Ativo desde 01/01/2022  R$ 5.000.000,00   4 Fontes
    01    Investimento 1            1.500.000,00 
    02    Investimento 2            2.500.000,00 
    03    Investimento 3              500.000,00  
    04    Investimento 4              500.000,00

002-X Willie outro Cliente        Ativo desde 01/01/2022  R$ 5.000.000,00   3 Fontes
    01    Investimento 1            1.500.000,00 
    02    Investimento 2            2.500.000,00 
    03    Investimento 3            1.000.000,00  

001-X Jhonny um Cliente        Ativo desde 01/01/2022  R$ 1.500.000,00   1 Fontes
    01    Investimento 1            1.500.000,00 

 

E crie os dados em arquivos. É trivial manipular arquivos em C. A linguagem foi escrita para desenvolver um sistema onde tudo é arquivo (Unix). 

 

Use o formato trivial, csv, conhecido desde os 70. E leia usando scafn e família. Uma única linha consome os dados.

  • Curtir 1
  • 5 semanas depois...
  • Membro VIP
Postado

Olás... Não estou conseguindo criar tópico mas este se aproxima do meu desafio. Já consigo ler tabelas há algum tempo. O que quero agora é "apontar" pra uma área da memória - rom/flash e lê-la diretamente... ok também já consegui. Mas aparece o incômodo warning

const unsigned char *txt={"12345678abcdefgh"};
unsigned char t=&txt; //illegal conversion of pointer to integer

Lembrando que trabalho no micromundo dos mc's.

Como este lance de ponteiro ainda é meu p.n.s., será que mesmo funcionando ele corre o risco de criar vida própria durante o funcionamento e aplicar a lei de murphy? Existe contornos/soluções tranquilizadoras?

O curioso é que aqui não me deu warning:

// Online C compiler to run C program online
#include <stdio.h>
const unsigned int *txt={"12345678abcde"};
int main() {

unsigned int t=&txt;
    // Write C code here
    printf("End= ");
    printf("%x",t);
    

    return 0;
}

https://www.programiz.com/c-programming/online-compiler/

Na real:

extern unsigned int const *dados;
unsigned int t=&dados;//illegal conversion of pointer to integer

#asm
PSECT flash_dados,class=CODE,local,delta=2
GLOBAL _dados
_dados: //escritos diretamente na flash com a definção do assembler
dw 1000,2000,3000 //...
dw 12345,56789,03,04 //...
#endasm

@arfneto @Diego Mendes Rodrigues

obrigado 🙂

Postado
2 horas atrás, .if disse:
const unsigned char *txt={"12345678abcdefgh"};
unsigned char t=&txt; //illegal conversion of pointer to integer

 

Porque não consegue criar um tópico???

 

Não entendi a ideia aqui...

 

         txt

 

é o que?

 

        const unsigned char*

 

Acho que devia declarar assim, porque essa é a realidade: está declarando um nome, txt, e associando a um tipo.

 

É óbvio que se txt é const unsigned char* então *txt é char. Isso é C. Mas não é o que está declarando. Prefira sempre 

 

const unsigned char*        txt = {"12345678abcdefgh"}; // esta declarando txt e não *txt

 

Agora a segunda linha: declara t como unsigned char. E tenta inicializar com &txt. O operador '&' extrai o endereço. Então &txt é um endereço, o endereço da string. E aí tenta atribuir a um char e acha estranho o compilador reclamar? É outro tipo. unsigned char tem um byte. Um endereço tem 4 ou 8 dependendo da plataforma.

 

image.png.0cfda47e14f1e8630442f3f0fd7f15b5.png

Na real declarou t como unsigned int aqui e não char. Então dependendo da plataforma os dois tem 4 bytes.

 

 

 

Bem confuso.

 

EXEMPLO

 

considere o arquivo outro.c:

 

// so isso

unsigned char* const dados = {"valor externo"};

 

e o arquivo v1.c

 

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

extern char* const dados;

int main(void)
{
    const char txt[] = {"12345678abcdefgh"};

    char         buffer[80];
    const char*  outro = (const char*)&buffer;
    unsigned int t     = (unsigned int)&txt;

    printf("End 't' (local) = 0x%X\n", t);

    char* p = (char*)t;
    printf(
        "primeiro byte de txt usando o ponteiro salvo no "
        "int: \"%c\"\n",
        *p);
    p = dados;
    printf("End 'p' (externo) = 0x%p\n", p);
    printf(
        "usando o ponteiro para a area externa: "
        "\"%s\"\n",
        p);

    // outro = p; // cancela o programa: outro eh const
    //*(p + 1) = '%'; // cancela o programa: p eh const
    p        = (char*) outro;  // assim esta ok
    strcpy(buffer, txt);
    *(p + 1) = '%';    // outro não eh const
    printf("outro: \"%s\"\n", p);
    return 0;
}

 

 

E o resultado, em 32 bits:

 

End 't' (local) = 0x8FFB04
primeiro byte de txt usando o ponteiro salvo no int: "1"
End 'p' (externo) = 0x00947B34
usando o ponteiro para a area externa: "valor externo"
outro: "1%345678abcdefgh"

 

E veja se ajuda a entender o mecanismo disso...

 

CRIE UM TÓPICO. Esse tipo de exemplo é importante, eu acho. 

  • Curtir 1
  • Membro VIP
Postado
15 horas atrás, arfneto disse:

Então &txt é um endereço, o endereço da string. E aí tenta atribuir a um char e acha estranho o compilador reclamar?

Exatamente este é o ponto: preciso do endereço em forma de char (de fato int) pois ele vai ser argumento de uma função que vai achar os dados na flash... não necessariamente string. Um micro resumo:

#asm
PSECT txt_flash,class=CODE,local,delta=2
GLOBAL _flash_text
_flash_text:
dw 't'<<7+'e','x'<<7+'t','o'<<7+'1','2'<<7+'3','4'<<7+'5','6'<<7+'7','8'<<7+'9','&'<<7+'%'
#endasm

E a função pra extrair o texto

extern const unsigned int* flash_text;
unsigned int add=&flash_text
FLASH_READ(add); //retorna em dois registros do mc

Meio que está dando certo apesar do warning

Um detalhe: este mc (pic16fxx) tem word de 14bits e sabemos que não existe palavra de 14bits no c portanto este é um artifício pra juntar dois caracteres 7bits cada num word 14bits. Há economia considerável de memória. Numa busca vi que já se desafiaram a isto mas de forma complexa mas não da forma minimalista e simplória que me autopropus.

 

15 horas atrás, arfneto disse:

CRIE UM TÓPICO

Vou tentar talvez... Talvez na seção microcontroladores pois pode não ser totalmente inútil pros colegas de chão de fábrica. ... portanto sinta-se a vontade em não dar prosseguimento a este.

Agradeço a participação 🙂

  • Curtir 1
Postado
43 minutos atrás, .if disse:

preciso do endereço em forma de char (de fato int)

E só um endereço. Não tem forma, use cast ou union então. Usa um crosscompiler? Como compila?

 

Entendeu o que eu expliquei? leu o exemplo que escrevi? rodou?

  • Amei 1
  • Membro VIP
Postado

Casting deu certo! você é o cara!

add_flash=(unsigned int)&flash_text;

Sumiu o warning!

Qualquer dia publico o algoritmo todo no forum mc. Como disse, há economia significativa pro caso de mc 8 bits da família pic cuja flash é composta de palavas 14bits quando se deseja escrever muitos textos, menus e etc...(o meu caso).

Abç e receba um aperto de mão virtual! 😁

4 horas atrás, arfneto disse:

use cast ou union então

Só me bateu uma curiosidade de como union - uma das mais sinistras entidades do c - poderia ajudar a contornar isso.. mas xapralá... por hora me satisfez! 👍

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

Entendeu o que eu expliquei? leu o exemplo que escrevi? rodou?

 

?

 

4 horas atrás, .if disse:

Só me bateu uma curiosidade de como union - uma das mais sinistras entidades do c - poderia ajudar a contornar isso.. mas xapralá... por hora me satisfez!

 

union nada tem de sinistro. Apenas faz uma área de memória poder ser vista como várias coisas distintas, alternadamente.

 

union é bem amiga de programadores em Assembler porque facilita o acesso a buffers e bit masks

 

Veja essa

 

    union
    {
        // txt: tam vai ser definido pelos outros campos
        const char   txt[];
        unsigned int valor;   // 4 bytes
        uint32_t     valor4;  // 4 bytes
        struct  // anonima: não precisa de nome
        {
            unsigned char byte0;
            unsigned char byte1;
            unsigned char byte2;
            unsigned char byte3;
        };
    } multi;

 

Isso faz o que você queria. E mais. txt[] tem o mesmo endereço de valor. E de valor4. E pode acessar byte a byte. E então o tamanho de txt fica regulado pelo tamanho da maior coisa que tiver na union. No caso o int. Deixei um campo como uint32_t para lembrar que é bom usar esses tipos que já tem o tamanho no nome. Eles residem em stdint.h.

 

EXEMPLO

 

    multi.byte0 = '0';
    multi.byte1 = '1';
    multi.byte2 = '2';
    multi.byte3 = 0;

 

Isso vai fazer com que txt tenha o valor "012". Conveniente...

 

Um programa completo que usa os dois modos de que falei:
 

#include <stdint.h>
#include <stdio.h>

int main(void)
{
    union
    {
        // txt: tam vai ser definido pelos outros campos
        const char   txt[];
        unsigned int valor;   // 4 bytes
        uint32_t     valor4;  // 4 bytes
        struct  // anonima: não precisa de nome
        {
            unsigned char byte0;
            unsigned char byte1;
            unsigned char byte2;
            unsigned char byte3;
        };
    } multi;

    multi.byte0 = '0';
    multi.byte1 = '1';
    multi.byte2 = '2';
    multi.byte3 = 0;

    const char* addr     = multi.txt;
    uint64_t    addr_int = (uint64_t)addr;

    printf("    txt[] = \"%s\"\n", multi.txt);
    printf(
        "    bytes: 0x%X 0x%X 0x%X 0x%X\n", multi.byte0,
        multi.byte1, multi.byte2, multi.byte3);
    multi.valor4 = 0x04030201;
    printf(
        "    valor agora = %d = 0x%X\n", multi.valor4,
        multi.valor4);
    printf(
        "    bytes: 0x%X 0x%X 0x%X 0x%X\n\n", multi.byte0,
        multi.byte1, multi.byte2, multi.byte3);

    printf(
        "    endereco de   'txt' = 0x%X\n",
        (unsigned int)multi.txt);
    printf(
        "    endereco de 'valor4'= 0x%X\n",
        (unsigned int)&multi.valor4);
    printf(
        "    endereco de 'byte0'\t= 0x%X\n",
        (unsigned int)&multi.byte0);
    printf(
        "    endereco de 'byte1'\t= 0x%X\n",
        (unsigned int)&multi.byte1);

    return 0;
}

 

Saida

 

    txt[] = "012"
    bytes: 0x30 0x31 0x32 0x0
    valor agora = 67305985 = 0x4030201
    bytes: 0x1 0x2 0x3 0x4

    endereco de   'txt' = 0xAFFDC8
    endereco de 'valor4'= 0xAFFDC8
    endereco de 'byte0' = 0xAFFDC8
    endereco de 'byte1' = 0xAFFDC9

 

Bem cômodo não é?

 

Ainda acha sinistro?

 

É muito conveniente.

 

Note que se precisa disso por exemplo para montar um header que vai usar toda hora pode declarar como nome:

 

typedef  union
{
    // txt: tam vai ser definido pelos outros campos
    const char   txt[];
    unsigned int valor;   // 4 bytes
    uint32_t     valor4;  // 4 bytes
    struct                // anonima: não precisa de nome
    {
        unsigned char byte0;
        unsigned char byte1;
        unsigned char byte2;
        unsigned char byte3;
    };
} Multi;

 

E declarar vários

 

    Multi teste;
    Multi muitos[20];

 

E escrever por exemplo

 

    muitos[19].byte3 = 0x23;

 

para acessar o ultimo byte da ultima uniao do array de 20.

  • Obrigado 1
  • Membro VIP
Postado
Em 01/08/2023 às 17:38, arfneto disse:
unsigned int t     = (unsigned int)&txt;

Percebo agora que seu bom exemplo já tinha a solução... sorry por não ter tido lido.

 

 

12 horas atrás, arfneto disse:
21 horas atrás, arfneto disse:

Entendeu o que eu expliquei? leu o exemplo que escrevi? rodou?

 

?

Ainda patino nos ponteiros, vetores e afins mesmo após anos. Mas reconheço seu valor que aos poucos me apontam 🤪

 

 P.ex. neste mesmo fonte uso este algoritmo

ponteiro = &dado; //localiza variável inteira dado 16 bits
*((unsigned char *)(ponteiro) + 0)=i2cr(12); //preenche seu conteúdo com 8 bits MSB e 
*((unsigned char *)(ponteiro) + 1)=i2cr(13); //LSB

gentilmente cedido pelo colega xults do asm51.com.br há muitos (e muitos) anos. De fato nem sei direito como funciona.. E nem ele mesmo se lembrava na época 😁

 

12 horas atrás, arfneto disse:

union nada tem de sinistro. Apenas faz uma área de memória poder ser vista como várias coisas distintas, alternadamente.

12 horas atrás, arfneto disse:

acesso a buffers e bit masks

De fato neste mesmo fonte uso este artifício pra registrar 3 status e uma informação de 4 bits em 1 byte na eeprom.. Portanto, lido com bits sim... e apesar de nossa distância, o que nos une é maior e você abrangeu muito bem 😁

Agradeço de novo seu tempo e empenho em compartilhar... tmj 🙃

  • Curtir 2
Postado
9 horas atrás, .if disse:

P.ex. neste mesmo fonte uso este algoritmo

ponteiro = &dado; //localiza variável inteira dado 16 bits
*((unsigned char *)(ponteiro) + 0)=i2cr(12); //preenche seu conteúdo com 8 bits MSB e 
*((unsigned char *)(ponteiro) + 1)=i2cr(13); //LSB

gentilmente cedido pelo colega xults do asm51.com.br há muitos (e muitos) anos. De fato nem sei direito como funciona.. E nem ele mesmo se lembrava na época 😁

 

Não dá pra dizer como funciona ou mesmo se funciona apenas vendo um pedaço de código. Mas são endereços consecutivos e são bytes então essa nem deve ser a mesma mais certinha de fazer isso.

 

C tem os mesmos operadores de bit que assembler e pode fazer igualzinho e usar AND OR XOR e NOT, e ROTATE e SHIFT. 

 

E como te mostrei no programa anterior pode usar uma union e acessar os bytes diretamente, veja no exemplo multi.byte0 e multi.byte1.

 

Veja esse programa com mais atenção ainda:

 

(C para programadores assembler 😄 )

 

#include <stdint.h>
#include <stdio.h>

typedef union
{
    unsigned char* ponteiro;
    uint32_t       dado;
    struct
    {
        unsigned char byte0;
        unsigned char byte1;
        unsigned char byte2;
        unsigned char byte3;
    };
} Coisa32;

int mostra(Coisa32*, const char*);

int main(void)
{
    unsigned char um    = 0xF2;
    unsigned char outro = 0xF3;

    Coisa32  teste = {0};
    Coisa32* p     = &teste;  // p aponta para teste...

    mostra(p, "zerado");

    teste.dado = teste.dado | (int)(um) << 8;  // byte 1
    mostra(p, "F2 no byte 2");

    teste.dado = teste.dado | (int)(outro) << 16;  // byte 2
    mostra(p, "F3 no byte 1" );

    teste.byte3 = 0xF4;
    mostra(p, "F3 no byte 3");

    teste.byte0 = 0xF1;
    mostra(p, "F1 no byte 0");

    teste.dado = 1;
    mostra(p, "int = 1");

    teste.dado = ~teste.dado;  // not
    mostra(p, "inverte bit a bit");

    // zera bits 0123 do byte3
    teste.byte3 = teste.byte3 & 0xF0;
    mostra(p, "zera 4 bits no byte 3");

    // coloca 8 no lugar
    teste.byte3 =  8;
    mostra(p,"coloca 8 no byte 3");

    // coloca 01010101 no byte 3
    teste.byte3 = 0b01010101;  // binário
    mostra(p, "coloca 01010101 = 55");

    // inverte o byte 3 0101 vira 1010 55 =? AA
    teste.byte3 = teste.byte3 ^ 0b11111111; // XOR
    mostra(p, "inverte o byte 3");

    // gira pra direita 8 bits
    teste.dado >>= 8;
    mostra(p, "shift 8 bits para a direita");

    // gira pra direita 8 bits
    teste.dado >>= 8;
    mostra(p, "shift 8 bits para a direita");

    // gira pra direita 8 bits
    teste.dado >>= 8;
    mostra(p, "shift 8 bits para a direita");

    // gira pra direita 8 bits
    teste.dado >>= 8;
    mostra(p, "shift 8 bits para a direita");

    return 0;
}

int mostra(Coisa32* campo, const char* tit)
{
    if (tit == NULL)
        printf(
            "%-20s\tvalor agora = %d\t[0x%08X]\n", " ",
            campo->dado, campo->dado);
    else
        printf(
            "%-20s\tvalor agora = %d\t[0x%08X]\n", tit,
            campo->dado, campo->dado);
    printf(
        "%20s\tbytes: 0x%X 0x%X 0x%X 0x%X\n\n",
        " ", campo->byte0,
        campo->byte1, campo->byte2, campo->byte3);
    return 0;
};

 

Eis a saida

 

zerado                  valor agora = 0 [0x00000000]
                        bytes: 0x0 0x0 0x0 0x0

F2 no byte 2            valor agora = 61952     [0x0000F200]
                        bytes: 0x0 0xF2 0x0 0x0

F3 no byte 1            valor agora = 15987200  [0x00F3F200]
                        bytes: 0x0 0xF2 0xF3 0x0

F3 no byte 3            valor agora = -185339392        [0xF4F3F200]
                        bytes: 0x0 0xF2 0xF3 0xF4

F1 no byte 0            valor agora = -185339151        [0xF4F3F2F1]
                        bytes: 0xF1 0xF2 0xF3 0xF4

int = 1                 valor agora = 1 [0x00000001]
                        bytes: 0x1 0x0 0x0 0x0

inverte bit a bit       valor agora = -2        [0xFFFFFFFE]
                        bytes: 0xFE 0xFF 0xFF 0xFF

zera 4 bits no byte 3   valor agora = -251658242        [0xF0FFFFFE]
                        bytes: 0xFE 0xFF 0xFF 0xF0

coloca 8 no byte 3      valor agora = 150994942 [0x08FFFFFE]
                        bytes: 0xFE 0xFF 0xFF 0x8

coloca 01010101 = 55    valor agora = 1442840574        [0x55FFFFFE]
                        bytes: 0xFE 0xFF 0xFF 0x55

inverte o byte 3        valor agora = -1426063362       [0xAAFFFFFE]
                        bytes: 0xFE 0xFF 0xFF 0xAA

shift 8 bits para a direita     valor agora = 11206655  [0x00AAFFFF]
                        bytes: 0xFF 0xFF 0xAA 0x0

shift 8 bits para a direita     valor agora = 43775     [0x0000AAFF]
                        bytes: 0xFF 0xAA 0x0 0x0

shift 8 bits para a direita     valor agora = 170       [0x000000AA]
                        bytes: 0xAA 0x0 0x0 0x0

shift 8 bits para a direita     valor agora = 0 [0x00000000]
                        bytes: 0x0 0x0 0x0 0x0

 

Acho mesmo importante você entender isso. Veja quando tiver tempo. São operações comuns em C e os operadores são os mesmos do assembler.

 

C foi escrita para escrever um sistema operacional (Unix) que era todo escrito em assembler em uma máquina com palavra de 18 bits 😄 

 

Esse programa faz aquilo que mostrou acima, mas vai achar talvez mais legível. E mostra outras coisas.

 

Se não entender algo pergunte, talvez abrindo um tópico com esse programa. O programa pode ajudar mais gente do que aqui enterrado nessa outra discussão se estiver separado

  • Curtir 2
  • Membro VIP
Postado
16 horas atrás, arfneto disse:

Não dá pra dizer como funciona ou mesmo se funciona apenas vendo um pedaço de código

ok mas se eu disser que funciona tem algum valor?😁 Então funciona sim amigo! Fiquei olhando pra isso durante anos e deduzi simploriamente que

ponteiro = &dado; //localiza variável inteira dado 16 bits

dado ocupa 2 bytes na ram. ponteiro acha ele.

*((unsigned char *)(ponteiro) + 0)=i2cr(12); //preenche seu conteúdo com 8 bits MSB e 
*((unsigned char *)(ponteiro) + 1)=i2cr(13); //LSB

agora que achou, *ponteiro+0  preenche seu conteúdo com um byte e *ponteiro+1 com o outro. i2cr() retorna 1 byte de 8 bits - cujo endereço é o argumento - gravados duma memória eeprom i2c. De fato isso adveio de uma necessidade de gravar/ler um float 32bits numa eeprom i2c o que ficou algo como:

float dado;
ponteiro = &dado; //localiza variável float dado 32 bits
*((unsigned char *)(ponteiro) + 0)=i2cr(12); //+0=só pra harmonia visual
*((unsigned char *)(ponteiro) + 1)=i2cr(13); //
*((unsigned char *)(ponteiro) + 2)=i2cr(14); //
*((unsigned char *)(ponteiro) + 3)=i2cr(15); //

E havia feito isso com union e struct mas achei a solução acima mais elegante e minimalista. Re-percebo agora que a solução casting da minha inquietação já estava a mão há anos 😁.

 

Vou analisar suas outras soluções sim! Pode ser útil quando eu usar um mc que não seja um pic10f2xx com seus infinitos 256bytes de rom e 15 de ram 😁

 

E descobri porque não estou conseguindo criar tópico 🤪. A qualquer momento vou publicar alguma contribuição sobre o tema otimização do uso de memória pra mc de baixa capacidade no forum microcontroladores com a técnica que desenvolvi... Mas confesso que pode não ser totalmente útil pois hoje em dia os mc's estão maiores de recursos e baratos.

Mas pelo menos vou descarregar algo lá.. ou puxar a descarga kk

 

abç & sucesso!

Postado
2 horas atrás, .if disse:
float dado;
ponteiro = &dado; //localiza variável float dado 32 bits
*((unsigned char *)(ponteiro) + 0)=i2cr(12); //+0=só pra harmonia visual
*((unsigned char *)(ponteiro) + 1)=i2cr(13); //
*((unsigned char *)(ponteiro) + 2)=i2cr(14); //
*((unsigned char *)(ponteiro) + 3)=i2cr(15); //

E havia feito isso com union e struct mas achei a solução acima mais elegante e minimalista

 

Bem, é um caso de opinião talvez. Não me parece minimalista. E não é genérica. E é difícil de ler com esses asteriscos todos. E eu não diria que é elegante. Coisa de forum isso de opinião 😉 Eu te mostrei a diferença e acho que você já sabia, mas veja de novo  usando o que te mostrei acima, para fazer a mesma coisa:

 

    Dado32 um  = {0};
    um.byte0  = i2cr(12);
    um.byte1  = i2cr(13);
    um.byte2  = i2cr(14);
    um.byte3  = i2cr(15);

    Dado32 outro = {
        .byte0 = i2cr(12),
        .byte1 = i2cr(13),
        .byte2 = i2cr(14),
        .byte3 = i2cr(15)};

 

E pode usar sempre esse tipo Dado32 que dá pra imaginar o que é mesmo sem o comentário... A segunda opção permite inicializar um único byte se for preciso.

 

typedef union
{
    unsigned char* ponteiro;
    float          dado;
    uint32_t       int32bits;
    struct
    {
        unsigned char byte0;
        unsigned char byte1;
        unsigned char byte2;
        unsigned char byte3;
    };
} Dado32;

 

Uma DWORD picadinha... 🙂 

 

É mais fácil imaginar que para mudar o byte 2 muda byte2, ou não?

 

E pode ter um WORD e um BYTE como a microsoft usa... Direto de windows.h:

 

typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;

 

Mas considere sempre usar os tipos que estão em stdint.h porque é melhor para todo mundo:

 

typedef signed char        int8_t;
typedef short              int16_t;
typedef int                int32_t;
typedef long long          int64_t;
typedef unsigned char      uint8_t;
typedef unsigned short     uint16_t;
typedef unsigned int       uint32_t;
typedef unsigned long long uint64_t;

 

mesmo que programe sozinho sempre. Um dia vai ler um programa de alguém e vai gostar de ler nomes com os quais está acostumado.

 

  • Curtir 1
  • mês depois...
Postado
Em 02/08/2023 às 13:53, .if disse:

Só me bateu uma curiosidade de como union - uma das mais sinistras entidades do c - poderia ajudar a contornar isso..

union também vem a ser útil para distinguir a maior constante.

union.txt

Postado

@hekotes630 Não falo pelo forum, mas incluir um link para um texto de 1k não é assim útil. Apenas mostre o texto aqui e não links.

 

Use o botão code como explicado no primeiro post do forum

 

Para quem queria saber o que tinha no tal link union.txt e a diferença que faria colocar o código aqui:

 

#include <stdio.h>
#include <time.h>

#define MON_1 "January"
#define MON_2 "February"
#define MON_3 "March"
#define MON_4 "April"
#define MON_5 "May"
#define MON_6 "June"
#define MON_7 "July"
#define MON_8 "August"
#define MON_9 "September"
#define MON_10 "October"
#define MON_11 "November"
#define MON_12 "December"
#define WDAY_1 "Sunday"
#define WDAY_2 "Monday"
#define WDAY_3 "Tuesday"
#define WDAY_4 "Wednesday"
#define WDAY_5 "Thursday"
#define WDAY_6 "Friday"
#define WDAY_7 "Saturday"

int main(void)
{
  time_t t = time(NULL);
  struct tm *t_tm = gmtime(&t);
  char *t_wday[] = {
    WDAY_1,
    WDAY_2,
    WDAY_3,
    WDAY_4,
    WDAY_5,
    WDAY_6,
    WDAY_7
  },
  *t_mon[] = {
    MON_1,
    MON_2,
    MON_3,
    MON_4,
    MON_5,
    MON_6,
    MON_7,
    MON_8,
    MON_9,
    MON_10,
    MON_11,
    MON_12
  },
  t_arr[sizeof(union {
    char mon[sizeof MON_1],
    mon2[sizeof MON_2],
    mon3[sizeof MON_3],
    mon4[sizeof MON_4],
    mon5[sizeof MON_5],
    mon6[sizeof MON_6],
    mon7[sizeof MON_7],
    mon8[sizeof MON_8],
    mon9[sizeof MON_9],
    mon10[sizeof MON_10],
    mon11[sizeof MON_11],
    mon12[sizeof MON_12];
  }) + sizeof(union {
    char wday[sizeof WDAY_1],
    wday2[sizeof WDAY_2],
    wday3[sizeof WDAY_3],
    wday4[sizeof WDAY_4],
    wday5[sizeof WDAY_5],
    wday6[sizeof WDAY_6],
    wday7[sizeof WDAY_7];
  }) + sizeof "00 00:00:00 0000"];

  sprintf(t_arr, "%s %s %d %d:%d:%d %d", t_wday[t_tm->tm_wday], t_mon[t_tm->tm_mon], t_tm->tm_mday, t_tm->tm_hour, t_tm->tm_min, t_tm->tm_sec, t_tm->tm_year + 1900);
  printf("%s\n", t_arr);
}

 

E agora que tem o código...

 

É ruim de ler isso. E não parece muito útil. Desde sempre isso está resolvido em time.h e locale.h...

 

Para que serve isso se já está usando time.h?

 

Veja o simples:
 

    strftime(
        buffer, sizeof(buffer),
        "Mes abreviado \"%b\" completo \"%B\"",
        info);
    printf("%s\n", buffer);

 

Que mostraria

 

        Mes abreviado "Sep" completo "September"

 

Para o locale padrão, `C`

 

Depois de algum recortar e colar, eis um exemplo dos valores

 

#include <locale.h>
#include <stdio.h>
#include <time.h>

int main()
{
    time_t     rawtime;
    struct tm* info;
    char       buffer[250];

    char* p = setlocale(LC_TIME, NULL);
    printf("locale atual: %s\n\n", p);

    time_t agora;
    time(&agora);
    info = localtime(&agora);

    strftime(
        buffer, sizeof(buffer),
        "Dia \"%u\" da semana (segunda = 1) "
        "abreviado \"%a\"\tcompleto \"%A\"",
        info);
    printf("Dias da semana: %s\n\n", buffer);

    strftime(
        buffer, sizeof(buffer),
        "Mes abreviado \"%b\" completo \"%B\"",
        info);
    printf("%s\n", buffer);

    setlocale(LC_TIME, "pt_BR");
    p = setlocale(LC_TIME, NULL);
    printf("\n\nMuda o locale para pt_BR:\tlocale atual: %s\n\n", p);

    strftime(
        buffer, sizeof(buffer),
        "Dia \"%u\" da semana (segunda = 1) "
        "abreviado \"%a\"\tcompleto \"%A\"",
        info);
    printf("Dias da semana: %s\n\n", buffer);

    strftime(
        buffer, sizeof(buffer),
        "Mes abreviado \"%b\" completo \"%B\"", info);
    printf("%s\n", buffer);

    return (0);
}

 

Que mostra

 

locale atual: C

Dias da semana: Dia "5" da semana (segunda = 1) abreviado "Fri" completo "Friday"

Mes abreviado "Sep" completo "September"


Muda o locale para pt_BR:       locale atual: pt_BR

Dias da semana: Dia "5" da semana (segunda = 1) abreviado "sex" completo "sexta-feira"

Mes abreviado "set" completo "setembro"

 

O fato de sizeof() mostrar o maior valor para uma union é bem esperado, afinal esse é o propósito: caber todas as alternativas, então o tamanho da união é o tamanho do maior possível conteúdo...

 

 

 

  • Curtir 1
Postado
Em 22/09/2023 às 11:50, arfneto disse:

Para que serve isso se já está usando time.h?

É apenas um exemplo de usabilidade do union. Se você tem várias constantes comuns e quer distinguir qual é maior, use o union.

 

No entanto, se você não quer alocar memória dinamicamente, declare uma constante longa, e declare um array de inteiro para distinguir o local da palavra.

 

#include <stdio.h>

#include <time.h>

 

#define MON_1 "January\0"

#define MON_2 "February\0"

#define MON_3 "March\0"

#define MON_4 "April\0"

#define MON_5 "May\0"

#define MON_6 "June\0"

#define MON_7 "July\0"

#define MON_8 "August\0"

#define MON_9 "September\0"

#define MON_10 "October\0"

#define MON_11 "November\0"

#define MON_12 "December"

#define WDAY_1 "Sunday\0"

#define WDAY_2 "Monday\0"

#define WDAY_3 "Tuesday\0"

#define WDAY_4 "Wednesday\0"

#define WDAY_5 "Thursday\0"

#define WDAY_6 "Friday\0"

#define WDAY_7 "Saturday"

 

int main(void)

{

  time_t t = time(NULL);

  struct tm *t_tm = gmtime(&t);

  int t_wdayp[] = {

    0,

    sizeof WDAY_1 - 1,

    sizeof WDAY_2 + t_wdayp[1] - 1,

    sizeof WDAY_3 + t_wdayp[2] - 1,

    sizeof WDAY_4 + t_wdayp[3] - 1,

    sizeof WDAY_5 + t_wdayp[4] - 1,

    sizeof WDAY_6 + t_wdayp[5] - 1

  },

  t_monp[] = {

    0,

    sizeof MON_1 - 1,

    sizeof MON_2 + t_monp[1] - 1,

    sizeof MON_3 + t_monp[2] - 1,

    sizeof MON_4 + t_monp[3] - 1,

    sizeof MON_5 + t_monp[4] - 1,

    sizeof MON_6 + t_monp[5] - 1,

    sizeof MON_7 + t_monp[6] - 1,

    sizeof MON_8 + t_monp[7] - 1,

    sizeof MON_9 + t_monp[8] - 1,

    sizeof MON_10 + t_monp[9] - 1,

    sizeof MON_11 + t_monp[10] - 1

  };

  char t_wday[] =

    WDAY_1

    WDAY_2

    WDAY_3

    WDAY_4

    WDAY_5

    WDAY_6

    WDAY_7

  ,

  t_mon[] =

    MON_1

    MON_2

    MON_3

    MON_4

    MON_5

    MON_6

    MON_7

    MON_8

    MON_9

    MON_10

    MON_11

    MON_12

  ;

 

  printf("%s %s %d %d:%d:%d %d\n", &t_wday[t_wdayp[t_tm->tm_wday]], &t_mon[t_monp[t_tm->tm_mon]], t_tm->tm_mday, t_tm->tm_hour, t_tm->tm_min, t_tm->tm_sec, t_tm->tm_year + 1900);

}

 

Isso pode usar um pouco mais de memória, devido aos arrays de inteiro, mas é um método que não aloca memória dinamicamente. Não é complacente com ANSI C89.

 

Para ANSI C89, defina diretivas de pré-processador.

 

#include <stdio.h>
#include <time.h>

#define MON_1 "January\0"
#define MON_2 "February\0"
#define MON_3 "March\0"
#define MON_4 "April\0"
#define MON_5 "May\0"
#define MON_6 "June\0"
#define MON_7 "July\0"
#define MON_8 "August\0"
#define MON_9 "September\0"
#define MON_10 "October\0"
#define MON_11 "November\0"
#define MON_12 "December"
#define WDAY_1 "Sunday\0"
#define WDAY_2 "Monday\0"
#define WDAY_3 "Tuesday\0"
#define WDAY_4 "Wednesday\0"
#define WDAY_5 "Thursday\0"
#define WDAY_6 "Friday\0"
#define WDAY_7 "Saturday"
#define MON_1P 0
#define MON_2P sizeof MON_1 - 1
#define MON_3P sizeof MON_2 + MON_2P - 1
#define MON_4P sizeof MON_3 + MON_3P - 1
#define MON_5P sizeof MON_4 + MON_4P - 1
#define MON_6P sizeof MON_5 + MON_5P - 1
#define MON_7P sizeof MON_6 + MON_6P - 1
#define MON_8P sizeof MON_7 + MON_7P - 1
#define MON_9P sizeof MON_8 + MON_8P - 1
#define MON_10P sizeof MON_9 + MON_9P - 1
#define MON_11P sizeof MON_10 + MON_10P - 1
#define MON_12P sizeof MON_11 + MON_11P - 1
#define WDAY_1P 0
#define WDAY_2P sizeof WDAY_1 - 1
#define WDAY_3P sizeof WDAY_2 + WDAY_2P - 1
#define WDAY_4P sizeof WDAY_3 + WDAY_3P - 1
#define WDAY_5P sizeof WDAY_4 + WDAY_4P - 1
#define WDAY_6P sizeof WDAY_5 + WDAY_5P - 1
#define WDAY_7P sizeof WDAY_6 + WDAY_6P - 1

int main(void)
{
  time_t t = time(NULL);
  struct tm *t_tm = gmtime(&t);
  int t_wdayp[] = {
    WDAY_1P,
    WDAY_2P,
    WDAY_3P,
    WDAY_4P,
    WDAY_5P,
    WDAY_6P,
    WDAY_7P
  },
  t_monp[] = {
    MON_1P,
    MON_2P,
    MON_3P,
    MON_4P,
    MON_5P,
    MON_6P,
    MON_7P,
    MON_8P,
    MON_9P,
    MON_10P,
    MON_11P,
    MON_12P
  };
  char t_wday[] =
    WDAY_1
    WDAY_2
    WDAY_3
    WDAY_4
    WDAY_5
    WDAY_6
    WDAY_7
  ,
  t_mon[] =
    MON_1
    MON_2
    MON_3
    MON_4
    MON_5
    MON_6
    MON_7
    MON_8
    MON_9
    MON_10
    MON_11
    MON_12
  ;

  printf("%s %s %d %d:%d:%d %d\n", &t_wday[t_wdayp[t_tm->tm_wday]], &t_mon[t_monp[t_tm->tm_mon]], t_tm->tm_mday, t_tm->tm_hour, t_tm->tm_min, t_tm->tm_sec, t_tm->tm_year + 1900);
}

Postado
6 horas atrás, hekotes630 disse:

#define MON_1 "January\0"

 

Para que 2 NULL ao fim de cada valor? E para que cada valor? E sobre esse WDAY_7?

 

6 horas atrás, hekotes630 disse:

#define WDAY_6 "Friday\0"
#define WDAY_7 "Saturday"

 

Espero que isso não venha de algum programa de produção: entenda que qualquer mudança em locale vai arruinar tudo isso. Mais uma vez veja o exemplo que deixei: uma chamada a set_locale e "Friday" vira "sexta-feira"

 

Sugiro fazer o simples e acreditar na razão de existir time.h, locale.h e coisas assim. Toda essa conta que está fazendo é para achar o tamanho máximo necessário para gerar uma mensagem de log...
 

Em 22/09/2023 às 11:50, arfneto disse:
// ...
    mon11[sizeof MON_11],
    mon12[sizeof MON_12];
  }) + sizeof(union {
    char wday[sizeof WDAY_1],
    wday2[sizeof WDAY_2],
    wday3[sizeof WDAY_3],
    wday4[sizeof WDAY_4],
    wday5[sizeof WDAY_5],
    wday6[sizeof WDAY_6],
    wday7[sizeof WDAY_7];
  }) + sizeof "00 00:00:00 0000"];

 

 

Use strftime e snprintf. Se mudar o idioma do sistema essa coisa ultra difícil de ler não vai rodar mais.... Pior, vai rodar apenas às vezes.

 

Recomendo seguir o exemplo que mostrei.

 

Isso é uma tentativa de recriar strftime(): 

 

6 horas atrás, hekotes630 disse:

printf("%s %s %d %d:%d:%d %d\n", &t_wday[t_wdayp[t_tm->tm_wday]], &t_mon[t_monp[t_tm->tm_mon]], t_tm->tm_mday, t_tm->tm_hour, t_tm->tm_min, t_tm->tm_sec, t_tm->tm_year + 1900);

 

Entenda porque strftime() e snprintf() por exemplo retornam um int com o tamanho da string de saída ou um valor negativo ou zero em caso de erro...

 

Sim, os caras pensaram exatamente nisso.

 

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

Para que 2 NULL ao fim de cada valor?

Percebeu que eu não usei vírgulas em t_mon[] e t_wday[]? É uma string literal concatenada. NULL só é atribuído à última concatenação.

 

Se precisar usar apenas uma constante, é só passar o endereço de acordo com o tamanho parametrizado. Para distinguir durante a execução, no entanto, é necessário declarar um array de inteiro, assim como eu fiz.

 

9 horas atrás, hekotes630 disse:

Isso pode usar um pouco mais de memória, devido aos arrays de inteiro.

Sobre isso, as declarações t_wday[] e t_mon[] não são necessárias.

 

#include <stdio.h>
#include <time.h>

 

#define MON_1 "January\0"
#define MON_2 "February\0"
#define MON_3 "March\0"
#define MON_4 "April\0"
#define MON_5 "May\0"
#define MON_6 "June\0"
#define MON_7 "July\0"
#define MON_8 "August\0"
#define MON_9 "September\0"
#define MON_10 "October\0"
#define MON_11 "November\0"
#define MON_12 "December"
#define WDAY_1 "Sunday\0"
#define WDAY_2 "Monday\0"
#define WDAY_3 "Tuesday\0"
#define WDAY_4 "Wednesday\0"
#define WDAY_5 "Thursday\0"
#define WDAY_6 "Friday\0"
#define WDAY_7 "Saturday"
#define MON_1P 0
#define MON_2P sizeof MON_1 - 1
#define MON_3P sizeof MON_2 + MON_2P - 1
#define MON_4P sizeof MON_3 + MON_3P - 1
#define MON_5P sizeof MON_4 + MON_4P - 1
#define MON_6P sizeof MON_5 + MON_5P - 1
#define MON_7P sizeof MON_6 + MON_6P - 1
#define MON_8P sizeof MON_7 + MON_7P - 1
#define MON_9P sizeof MON_8 + MON_8P - 1
#define MON_10P sizeof MON_9 + MON_9P - 1
#define MON_11P sizeof MON_10 + MON_10P - 1
#define MON_12P sizeof MON_11 + MON_11P - 1
#define WDAY_1P 0
#define WDAY_2P sizeof WDAY_1 - 1
#define WDAY_3P sizeof WDAY_2 + WDAY_2P - 1
#define WDAY_4P sizeof WDAY_3 + WDAY_3P - 1
#define WDAY_5P sizeof WDAY_4 + WDAY_4P - 1
#define WDAY_6P sizeof WDAY_5 + WDAY_5P - 1
#define WDAY_7P sizeof WDAY_6 + WDAY_6P - 1
#define MONTH MON_1 MON_2 MON_3 MON_4 \
        MON_5 MON_6 MON_7 MON_8 \
        MON_9 MON_10 MON_11 MON_12
#define WEEK WDAY_1 WDAY_2 WDAY_3 WDAY_4 \
        WDAY_5 WDAY_6 WDAY_7

 

int main(void)
{
  time_t t = time(NULL);
  struct tm *t_tm = gmtime(&t);
  int t_wday[] = {
    WDAY_1P,
    WDAY_2P,
    WDAY_3P,
    WDAY_4P,
    WDAY_5P,
    WDAY_6P,
    WDAY_7P
  },
  t_mon[] = {
    MON_1P,
    MON_2P,
    MON_3P,
    MON_4P,
    MON_5P,
    MON_6P,
    MON_7P,
    MON_8P,
    MON_9P,
    MON_10P,
    MON_11P,
    MON_12P
  };

 

  printf("%s %s %d %d:%d:%d %d\n", &WEEK[t_wday[t_tm->tm_wday]], &MONTH[t_mon[t_tm->tm_mon]], t_tm->tm_mday, t_tm->tm_hour, t_tm->tm_min, t_tm->tm_sec, t_tm->tm_year + 1900);
}

  • Curtir 1
Postado

 

 

@hekotes630 Vou explicar de novo porque esse tópico (antigo) tem mais de 1300 visualizações e outros também podem entender...

 

1 hora atrás, hekotes630 disse:

Percebeu que eu não usei vírgulas em t_mon[] e t_wday[]? É uma string literal concatenada. NULL só é atribuído à última concatenação.

 

Se precisar usar apenas uma constante, é só passar o endereço de acordo com o tamanho parametrizado. Para distinguir durante a execução, no entanto, é necessário declarar um array de inteiro, assim como eu fiz.

 

 

Não entendo o que quer dizer com isso.

 

1 hora atrás, hekotes630 disse:

#define WDAY_6 "Friday\0"
#define WDAY_7 "Saturday"

 

Entenda que "Saturday" por exemplo já inclui um NULL ao final. É C : "" já é uma string de um byte e  esse byte vale ZERO. Ao escrever "Friday\0" está usando um segundo NULL ao final. Pode até ser de propósito, por alguma razão obscura, mas entenda que pode nada significar, como em um const char* que use esse #define como

 

#define WDAY_6 "Friday\0"
const char* outra_coisa = WDAY_7;

 

O compilador vai parar no primeiro NULL. Entendeu? 

 

Pode ser que ajude a entender: veja o código gerado com gcc 13.2

 

.LC0:
        .string "ASaturday"
        .string ""
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     QWORD PTR [rbp-8], OFFSET FLAT:.LC0
        mov     rax, QWORD PTR [rbp-8]
        mov     rdi, rax
        call    puts
        mov     eax, 0
        leave
        ret

 

Para esse complexo programa

 

#define WDAY_7 "ASaturday\0"
#include <stdio.h>
int main(void)
{
    const char* outra_coisa = WDAY_7;
    printf("%s\n", outra_coisa);
    return 0;
}

 

Está vendo a segunda string lá? Trata-se de um vazamento de memória. Não faz parte de nada.

 

Sobre o código que postou agora, entenda que havia postado isso com o seguinte objetivo

 

12 horas atrás, hekotes630 disse:

É apenas um exemplo de usabilidade do union. Se você tem várias constantes comuns e quer distinguir qual é maior, use o union.

 

 

Pois é. Só que agora o código não tem mais union... Qual o propósito então?

 

E repito: ao mudar o locale --- ou se não for o que você imagina, já que sequer testou --- seu programa vai falhar, a menos que tenha a intenção mesmo de forçar o uso de algum locale para inglês. E aí porque não chamar simplesmente setlocale(LC_TIME,"en_US") por exemplo?

 

Tudo que esse programa faz é mostrar isso:

 

Sunday September 24 3:45:52 2023

 

E não é o que mostrava o programa inicial que seria um exemplo do uso de union...

 

De todo modo, off-topic ou não, veja esse programa:

 

#include <locale.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
    struct tm* info;
    char       buffer[80];
    size_t     res = 0;
    char*      p   = NULL;
    p = setlocale(LC_TIME, NULL);
    time_t agora;
    time(&agora);
    info = localtime(&agora);
    res = strftime(
        buffer, sizeof(buffer), "%A %B %d  %H:%M:%S %Y",
        info);
    printf("[Locale \"%s\":\t%s [%llu]\n", p, buffer, res);
    return (0);
}

 

Que mostra 

 

[Locale "C":    Sunday September 24  01:07:19 2023 [34]

 

E é a mesma coisa que o programa que postou. Em buffer fica o timestamp, com 34 bytes, como informado por strftime() de modo que se precisar alocar um buffer e enviar isso para uma API de log é só usar esses valores.

 

Só que isso entende locale então se precisar disso em português ou alemão basta mudar LC_TIME.

 

Todo o programa que postou se resume a isso:

 

    res = strftime(
        buffer, sizeof(buffer), "%A %B %d  %H:%M:%S %Y",
        info);

 

Só que sequer considera o idioma. E tem todo aquele código.

 

Considere.

 

 

 

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

E para que cada valor?

Pode parecer inútil, mas é uma questão de parametrização. Se você usa uma constante em várias partes do programa e pretende mudá-la futuramente, é conveniente parametrizá-la. Isso pode ser visto mais facilmente em meu exemplo de usabilidade do union.

 

2 horas atrás, arfneto disse:

E repito: ao mudar o locale --- ou se não for o que você imagina, já que sequer testou --- seu programa vai falhar, a menos que tenha a intenção mesmo de forçar o uso de algum locale para inglês.

Por isso eu usei diretivas de pré-processador. Parametrização. Defina uma vez; use em várias partes.

 

2 horas atrás, arfneto disse:

Entenda que "Saturday" por exemplo já inclui um NULL ao final.

E porque eu definiria desta forma se o propósito é para uso em uma string literal concatenada? Não faz sentido usar para outro propósito.

  • Curtir 1
Postado
7 horas atrás, hekotes630 disse:

E porque eu definiria desta forma se o propósito é para uso em uma string literal concatenada? Não faz sentido usar para outro propósito

 

Está bem, vou explicar só mais uma vez, para outros: quanto você escreve "Saturday" o compilador insere um NULL ao final da string. É assim nessa linguagem.

 

Quando você escreve, como fez exceto em uma linha que deve ter esquecido, algo assim

12 horas atrás, hekotes630 disse:

#define MON_1 "January\0"
#define MON_2 "February\0"
#define MON_3 "March\0"
#define MON_4 "April\0"
#define MON_5 "May\0"
#define MON_6 "June\0"
#define MON_7 "July\0"
#define MON_8 "August\0"
#define MON_9 "September\0"
#define MON_10 "October\0"
#define MON_11 "November\0"
#define MON_12 "December"
#define WDAY_1 "Sunday\0"
#define WDAY_2 "Monday\0"
#define WDAY_3 "Tuesday\0"
#define WDAY_4 "Wednesday\0"
#define WDAY_5 "Thursday\0"
#define WDAY_6 "Friday\0"
#define WDAY_7 "Saturday"

 

Está apenas deixando em cada caso um NULL inacessível lá a cada vez que usa isso. Eu até te mostrei o código gerado para um caso desses.

 

Entenda que ao usar isso como string, em chamadas de função ou para inicializar algo, o compilador vai gerar código para para no primeiro NULL. É ingênuo colocar outros lá a menos que algo obscuro como esconder uma string depois disso.

 

7 horas atrás, hekotes630 disse:

Por isso eu usei diretivas de pré-processador. Parametrização. Defina uma vez; use em várias partes.

 

 

Como expliquei, não é boa ideia: essa parametrização é coisa de runtime. Não está fazendo nada útil inventando constantes para valores que já existem e aplicando valores em tempo de compilação.

 

Não há razão para escrever dezenas e dezenas de linha de código ruim de ler para apenas replicar uma chamada de sistema de UMA LINHA como eu te mostrei.

 

E que tipo de parametrização em tempo de compilação FIXA uma linguagem e ignora a biblioteca de parametrização em locale.h?

 

Tenho aqui na mesma mesa computadores com versões de sistema em vários idiomas. Acha que eu iria querer um programa personalizável que fixa os nomes dos dias da semana e meses? 

 

Eu não corrijo seus programas, você não trabalha para mim, mas por certo eu não usaria um programa desses: entenda os argumentos e os exemplos que mostrei. 

 

Não é só minha opinião.

 

  • Curtir 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...

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!