Dúvida Iniciante com Struct em C Puro [RESOLVIDO]

13. Re: Dúvida Iniciante com Struct em C Puro [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 17/08/2019 - 02:15h

Nick-us escreveu:

Primeiramente obrigado por responder... Eu procurei simplificar ao máximo o exemplo, mas talvez tenha simplificado demais, Então vou tentar explicar melhor.

Quando eu criei a Struct e o Vetor meu objetivo é que eles fossem exatamente parecidos para comparar em minha dúvida
struct DbNames {
char Names[5];
};
struct DbNames List[] = { {"A"}, {"B"}, {"C"} };
char Text[] = "ABC";

O que entendo: Nos 2 Casos, Eu teria 1 vetor contendo 3 caracteres. Tipo:
Text[0] = A
Text[1] = B
Text[2] = C
Text[3] = 0 ou /0 (O Caracter Terminador do vetor)


O conteúdo de Text é realmente esse, mas note que isso contradiz o que você disse logo acima (que você teria um vetor com três caracteres). Como você mesmo mostrou, percorreu quatro elementos do array, então ele não tem apenas três caracteres, mas sim quatro.

Motivo pelo qual mostro que ao comparar o CARACTER que não foi preenchido, a comparação ENCONTRA o caracter terminador.


Errado, porque esse caráter foi preenchido. Quando você usa a notação de constantes literais strings entre aspas, após fechar as última aspas, o compilador necessariamente insere o terminador se houver espaço no array ou se o espaço estiver sendo calculado em função do tamanho da string.

Imagino que o código abaixo ajude a ilustrar.

char s1[6]="Paulo";   // OK.
char s2[]="Paulo"; // OK: tamanho 6, calculado automaticamente porque o compilador considera a presença do terminador.
char s3[5]="Paulo"; // OK em C (em C++ seria um erro): o compilador omite o terminador porque acredita que você sabe
// o que está fazendo. s3 não pode ser considerado uma string, já que não possui o terminador.
char s4[4]="Paulo"; // Produz alerta em C (em C++ seria um erro), já que o se está sendo suprimido não é apenas o
// terminador implícito pelo uso das aspas, mas caráter explicitamente colocado ali.
char s5[4]="Paul\0"; // Produz alerta em C (em C++ seria um erro), já que o se está sendo suprimido não é apenas o
// terminador implícito pelo uso das aspas, mas caráter explicitamente colocado ali (mesmo
// que seja um byte nulo, que equivale a um terminador!).


if(Text[3] == 0)
puts("OK 1"); // WORK
if(Text[3] == '\0')
puts("OK 2"); // WORK

Porém no Caso da Struct List que também possue 3 Caracteres que podem ser identificados da mesma forma como:
List[0] = A
List[1] = B
List[2] = C


Como você fez para observar esses valores dessa forma? Não foi mandando imprimir “List[0]”, pois nenhuma função de impressão da biblioteca padrão aceitaria receber uma estrutura como parâmetro (isto é: printf("%s", List[0]) daria erro).

Ainda mais estranho se eu colocar:
puts(List[3].Names); // O Resultado é ABC Como isso é possível? Pois não deveria ter valor dentro da lógica, pois esse campo não foi preenchido 


Aqui você deu um tremendo azar. Você declarou, acima, primeiro List e depois Text, e o compilador reservou espaço para ambas na memória de um jeito em que a região de memória ocupada por Text veio logo depois da região de memória ocupada por List. Como você pediu para ter acesso ao quarto elemento de List (i.e. List[3]), mas List só tinha espaço reservado para três elementos, essa extrapolação fez com que o endereço resultante invadisse o espaço de Text, que vinha logo em seguida.

O engraçado é que se você tivesse usado "XYZ" em Text e {{"A"}, {"B"}, {"C"}} em List, o que teria sido impresso teria sido “XYZ”, e você possivelmente não teria se confundido, e talvez até percebesse por conta própria a invasão do espaço de outro objeto.

E é por isso que eu chamo esses aparentes funcionamentos de azar, em vez de dizer que você deu sorte. Se o programa tivesse simplesmente capotado ou imprimido coisas espúrias, você logo teria visto o erro, e tentaria descobrir a causa. Com um resultado parecido com o que você gostaria, acabou se confundindo e se perdendo num mar de incertezas.

A Struct em si seria por exemplo:
List[0] = A, 0,0,0,0 porque ela tem espaço para 4 Caracteres + Terminador em Cada Linha
List[1] = B, 0,0,0,0 porque ela tem espaço para 4 Caracteres + Terminador em Cada Linha
List[2] = C, 0,0,0,0 porque ela tem espaço para 4 Caracteres + Terminador em Cada Linha


Mais ou menos isso. Mas seria melhor de você indicasse os caracteres não-nulos como faz o C: “'A', 0, 0, 0, 0”, “'B', 0, 0, 0, 0”, “'C', 0, 0, 0, 0”.

Então pensei que esse seria o valor de List[3]
List[3] = 0,0,0,0,0 porque ela tem espaço para 4 Caracteres + Terminador em Cada Linha 

Nesse meio tempo, vi que uma forma de saber qts registros possue uma Struct seria esse abaixo, FUNCIONOU mas não sei se é assim mesmo que se verifica.
size_t size = sizeof List / sizeof List[0];
printf("%d\n", size);


Sim, essa é a forma usual de saber quantos elementos tem um array. Mas o resultado disso, no seu caso, deve ter sido 3, e não 4, certo?

Só uma pequena ressalva. O tipo size_t pode ter um tamanho distinto do tamanho de int, e também é um tipo inteiro sem sinal. Então a melhor forma de imprimir dados do tipo size_t por meio de printf() é com a conversão "%zu" (onde 'z' é um modificador do tamanho do dado, e 'u' é a conversão de tipos inteiros sem sinal).

Uma idéia que me deram seria preencher um valor nulo como um registro, assim eu encontraria o 0 no final dela ao varrer a Struct.
struct DbNames List[] = { {"A"}, {"B"}, {"C"}, {"0"} }; 

Porém também achei isso deselegante, pq fiquei pensando, será que não existe uma forma de identificar o final de uma Struct?


O final da estrutura ou o final do array de estruturas? No seu caso, List é um array, e cada um de seus elementos é que denota uma estrutura.


... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)


  



01 02



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts