Como declarar corretamente char* em C [RESOLVIDO]

1. Como declarar corretamente char* em C [RESOLVIDO]

Apprentice X
ApprenticeX

(usa Slackware)

Enviado em 06/11/2021 - 22:57h

Boa Noite a todos!

Como devo declarar corretamente em C?
OBS:
O Espaço vazio é porque desejo preencher este campo depois via código.
Estou confuso porque muitos exemplos que vi com ponteiros, não é declarado um caracter terminador, porém vejo também exemplos que declaram com o caracter terminador que mostro abaixo.


Não declarei um caracter terminador {"Texto1", "", 0}, Seria necessário no caso abaixo?
char *Matriz[3][2] = {
{"Texto1", ""}, // {"Texto1", "", 0}, Preciso declarar assim?
{"Texto2", ""},
{"Texto3", ""},
};



  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 07/11/2021 - 20:14h

ApprenticeX escreveu:

Boa Noite a todos!

Como devo declarar corretamente em C?
OBS:
O Espaço vazio é porque desejo preencher este campo depois via código.
Estou confuso porque muitos exemplos que vi com ponteiros, não é declarado um caracter terminador, porém vejo também exemplos que declaram com o caracter terminador que mostro abaixo.


Não declarei um caracter terminador {"Texto1", "", 0}, Seria necessário no caso abaixo?
char *Matriz[3][2] = {
{"Texto1", ""}, // {"Texto1", "", 0}, Preciso declarar assim?
{"Texto2", ""},
{"Texto3", ""},
};


Com a declaração acima, você está dizendo que o identificador Matriz tem o tipo “array com três elementos do tipo «array com dois elementos do tipo ‘ponteiro para caracteres’»”. Isso implica que Matriz[n] (com n inteiro maior ou igual a 0 e menor que 3) será um objeto do tipo “array com dois elementos do tipo «ponteiro para caracteres»”, e Matriz[n][m] (com m inteiro maior ou igual a 0 e menor que 2) é do tipo “ponteiro para caracteres” (que é sinônimo de “endereço de região de memória onde há dado do tipo caráter”).

Note que a quantidade total de elementos individuais do tipo char * (ou ponteiro para caracteres) de Matriz é seis (3*2==6).

Observando a lista de inicialização que se atribui a Matriz junto com a declaração (que, por sinal, é o único momento em que é possível fazer atribuições diretas a arrays em C e C++), vemos que há exatamente seis elementos, e que tais elementos estão dispostos como três blocos de dois elementos. Isso é consistente com a declaração: Matriz tem três elementos, cada um deles sendo um array com dois elementos, dispostos como abaixo.

  • Matriz[0] corresponde a {"Texto1", ""}, implicando que Matriz[0][0] é associado a "Texto1" e Matriz[0][1] a "";
  • Matriz[1] corresponde a {"Texto2", ""}, implicando que Matriz[1][0] é associado a "Texto2" e Matriz[1][1] a "";
  • Matriz[2] corresponde a {"Texto3", ""}, implicando que Matriz[2][0] é associado a "Texto3" e Matriz[2][1] a "".

Essa disposição, por si só, já seria suficiente para mostrar por que razão não poderia ser usada a lista de inicialização {"Texto1", "", 0}, como na pergunta que você colocou num comentário no meio do código, pois ela tentaria colocar um terceiro elemento em Matriz[0], que é um array que só tem dois elementos. Se você tentar fazê-lo deve receber um erro de compilação, indicando que a lista de inicialização excedeu o tamanho do array.

Quando você levanta dúvidas sobre terminador, entendo que se refere ao byte nulo que indica o fim de uma string. Esse byte nulo é automaticamente colocado ao final da string quando você usa a notação de constantes literais entre aspas. Quando você usa, por exemplo, "Texto1" no seu código, está provocando a alocação em algum lugar da memória para sete caracteres, sendo os seis do texto que você vê e mais um para acomodar o byte terminador. De modo semelhante, uma suposta “string vazia”, indicada como "", não representa uma região de memória de tamanho zero, mas sim uma região com tamanho um, a fim de acomodar o byte nulo.

Outro ponto que eu quero destacar é que os elementos individuais (Matriz[n][m]) são ponteiros para caracteres, não os caracteres em si. As strings "Texto1", "Texto2", "Texto3" e "" (com seus respectivos terminadores) usados na declaração não estão dispostas dentro da memória alocada para os elementos de Matriz, mas em alguma outra região de memória reservada para constantes, e os endereços dessas regiões de memória para dados constantes são copiados para os elementos individuais Matriz[n][m], já que, como vimos acima, os tipos desses elementos é “ponteiro para caracteres”, logo guardam endereços de onde os caracteres eventualmente residem, não os caracteres em si.

Um aspecto infeliz do C, que foi corrigido em C++, é o descasamento entre o caráter constante de uma constante literal entre aspas e a possibilidade de usar um ponteiro para caracteres não caracterizado como constante para referir-se a ela. Sua declaração, embora válida em C, seria inválida em C++, e por boas razões, porque ela pode lhe trazer problemas mesmo C. Considere o seguinte programa.
#include <stdio.h>

char *Matriz[3][2] = {
{"Texto1", ""}, // {"Texto1", "", 0}, Preciso declarar assim?
{"Texto2", ""},
{"Texto3", ""},
};

int main(void){
Matriz[0][0][2]='s'; // Tenta transformar "Texto1" em "Testo1". Posso fazê-lo?
}

Se eu tentar compilar o programa acima como programa em C++, não vou conseguir, porque estarei tentando usar atribuir dados constantes a ponteiros que não são constantes, o que poderia me causar problemas na hora de manipular esses dados (e note que há um erro para cada elemento individual da matriz).
$ g++ -Wall -Werror -O2 -pedantic-errors x.c -o x
x.c:7:1: error: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
};
^
x.c:7:1: error: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
x.c:7:1: error: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
x.c:7:1: error: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
x.c:7:1: error: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
x.c:7:1: error: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]

Já uma tentativa de compilar o mesmo programa em C funciona sem nenhum problema, mas veja o que ocorre na hora em que eu executo o código produzido.
gcc -Wall -Werror -O2 -pedantic-errors x.c -o x  # Compila sem erro.

$ ./x # Executa o código compilado acima.
Segmentation fault (core dumped)

Tal erro ocorre porque eu tento escrever numa região de memória protegida contra escrita, já que, afinal, o que está nela é uma constante, assim expressa no próprio código fonte do programa, e tal tentativa provoca uma violação de proteção de memória, o que faz com que o sistema operacional mate o programa.

Para corrigir a declaração no programa acima (inclusive em C, do ponto de vista semântico), poderíamos fazer com que cada elemento individual de Matriz fosse um ponteiro para caracteres constantes.
#include <stdio.h>

const char *Matriz[3][2] = { {"Texto1", ""}, {"Texto2", ""}, {"Texto3", ""} };

int main(void){
// Se descomentada, a linha abaixo seria um erro, pois agora os caracteres apontados por cada elemento são constantes.
/*Matriz[0][0][2]='s';*/

// Isto é possível, pois usamos o ponteiro apenas para ler um caráter, não para modificá-lo.
return Matriz[0][0][2]; // Vai retornar o valor 120 (correspondente a 'x').
}

Note, porém, que isso transforma em constante apenas os dados apontados pelos elementos individuais de Matriz, não os elementos em si. Se, no exemplo acima, eu tivesse feito algo como “Matriz[0][0]="ABCDEF";” antes da linha contendo o comando return, o valor retornado teria sido 67 (correspondente a 'C'). Se quisesse impedir que as strings referenciadas por cada elemento da matriz não pudessem ser alteradas, eu teria de informar isso na declaração.

Veja se o exemplo abaixo ajuda.
#include <stddef.h>
#include <string.h>

// Declara algumas strings (arrays de caracteres incluindo byte terminador) não-constantes.
char sv1[]="Teste1", sv2[]="Teste2";

// Declara algumas strings (arrays de caracteres incluindo byte terminador) constantes.
const char sc1[]="TesteC1", sc2[]="TesteC2";

// Declara alguns arrays com elementos variáveis que não são strings (falta o byte terminador).
char av1[4]={'T','S','T','1'}, av2[4]={'T','S','T','2'};

// Declara alguns arrays com elementos constantes que não são strings (falta o byte terminador).
const char ac1[4]={'C','N','T','1'}, ac2[4]={'C','N','T','2'};


// Declara matriz de ponteiros (não-constantes) para caracteres (não-constantes).
// Nas listas de inicialização de elementos, não convém (em C++, não podemos) usar constantes literais entre aspas,
// já que os ponteiros não indicam dados constantes, mas podemos usar ponteiros para dados não-constantes, tais como
// as conversões a partir de arrays de caracteres não-constantes (sejam eles strings ou não), e o ponteiro nulo.
char *Matriz1[3][2]={ {sv1, sv2}, {av1, av2}, {NULL, NULL} };

// Declara matriz de ponteiros (não-constantes) para caracteres constantes.
// Nas listas de inicialização, podemos usar constantes literais entre aspas, já que os ponteiros indicam dados
// constantes, além de todos os outros casos de ponteiros para dados constantes ou variáveis, tais como os obtidos
// a partir de arrays, quer constituam strings ou não, e mais o ponteiro nulo.
const char *Matriz2[3][2]={ {"Texto1", sc1}, {sv1, ac1}, {av1, NULL} };

// Declara matriz de ponteiros constantes para caracteres (não-constantes).
// Nas listas de inicialização de elementos, não convém (em C++, não podemos) usar constantes literais entre aspas,
// já que os ponteiros, embora constantes, não indicam dados constantes, mas podemos usar ponteiros para dados
// não-constantes, tais como as conversões a partir de arrays de caracteres não-constantes (sejam eles strings
// ou não), e o ponteiro nulo.
char *const Matriz3[3][2]={ {NULL, NULL}, {sv1, sv2}, {av1, av2} };

// Declara matriz de ponteiros constantes para caracteres constantes.
// Nas listas de inicialização, podemos usar constantes literais entre aspas, já que os ponteiros indicam dados
// constantes, além de todos os outros casos de ponteiros para dados constantes ou variáveis, tais como os obtidos
// a partir de arrays, quer constituam strings ou não, e mais o ponteiro nulo.
const char *const Matriz4[3][2]={ {"Texto1", sv2}, {sc2, av2}, {ac2, NULL} };


int main(void){
size_t l;
char c;
char *pc;
const char *pcc;

// Com Matriz1, posso fazer:
pc=Matriz1[0][0]; // Obter o valor de qualquer elemento da matriz e atribuí-lo a um ponteiro para dados não-constantes (mesmo tipo).
pcc=Matriz1[0][1]; // Obter o valor de qualquer elemento da matriz e atribuí-lo a um ponteiro para dados constantes (tipo compatível).
c=Matriz1[0][1][0]; // Obter um dado apontado por qualquer elemento que seja um ponteiro válido e que não exceda os limites do dado apontado.
Matriz1[1][0]=sv2; // Alterar ponteiro contido em um dos elementos da matriz, desde que o tipo do novo valor seja compatível (não pode ser ponteiro para dados constantes, por exemplo).
Matriz1[1][1][0]=c; // Alterar um dado apontado por qualquer elemento que seja um ponteiro válido e que não exceda os limites do dado apontado.

// Com Matriz1, não posso fazer:
Matriz1[2][0]="Texto5"; // Alterar ponteiro contido em um dos elementos da matriz para se referir ao conteúdo de uma constante literal entre aspas (o C até permite, mas é periogoso, como já se viu; em C++, dá erro).
Matriz1[2][0]=pcc; // Alterar ponteiro contido em um dos elementos da matriz para se referir dados indicados como constantes (aqui, nem mesmo o compilador C deixa passar).

// O compilador não vai alarmar, mas eu também não devo fazer com Matriz1:
l=strlen(Matriz1[1][0]); // Usar dados que não são strings (porque eu sei que não têm o byte terminador) como se fossem strings.
Matriz1[0][1][100]=c; // Exceder os limites do conteúdo apontado por um dos elementos da matriz, quer seja para gravar conteúdo...
c=Matriz1[0][1][100]; // ... quer para ler conteúdo.
Matriz1[2][1][0]=c; // Como eu sei que este elemento da matriz contém um ponteiro inválido, não posso usar tal ponteiro para gravar conteúdo...
c=Matriz1[2][1][0]; // ... nem para ler conteúdo.


// Com Matriz2, posso fazer:
pcc=Matriz2[0][0]; // Obter o valor de qualquer elemento da matriz e atribuí-lo a um ponteiro para dados constantes (mesmo tipo).
c=Matriz2[0][0][0]; // Obter um dado apontado por qualquer elemento que seja um ponteiro válido e que não exceda os limites do dado apontado.
Matriz2[0][1]="Texto2"; // Alterar ponteiro contido em um dos elementos da matriz para se referir ao conteúdo de uma constante literal entre aspas (tipo compatível).
Matriz2[1][0]=sv2; // Alterar ponteiro contido em um dos elementos da matriz (o ponteiro original pode apontar para dados constantes ou dados variáveis).
Matriz2[1][1]=pcc; // Alterar ponteiro contido em um dos elementos da matriz para se referir dados indicados como constantes (aqui, nem mesmo o compilador C deixa passar).

// Com Matriz2, não posso fazer:
pc=Matriz2[0][0]; // Obter o valor de qualquer elemento da matriz e atribuí-lo a um ponteiro para dados não-constantes (tipo incompatível).
Matriz2[1][1][0]=c; // Alterar um dado apontado por qualquer elemento, independentemente do valor do ponteiro.

// O compilador não vai alarmar, mas eu também não devo fazer com Matriz2:
l=strlen(Matriz2[2][0]); // Usar dados que não são strings (porque eu sei que não têm o byte terminador) como se fossem strings.
c=Matriz2[0][1][100]; // Exceder os limites do conteúdo apontado por um dos elementos da matriz, mesmo que somente para ler conteúdo.
c=Matriz2[2][1][0]; // Como eu sei que este elemento da matriz contém um ponteiro inválido, não posso usar tal ponteiro nem mesmo para ler conteúdo.


// Com Matriz3, posso fazer:
pc=Matriz3[1][0]; // Obter o valor de qualquer elemento da matriz e atribuí-lo a um ponteiro para dados não-constantes (mesmo tipo).
pcc=Matriz3[1][1]; // Obter o valor de qualquer elemento da matriz e atribuí-lo a um ponteiro para dados constantes (tipo compatível).
c=Matriz3[1][1][0]; // Obter um dado apontado por qualquer elemento que seja um ponteiro válido e que não exceda os limites do dado apontado.
Matriz3[2][1][0]=c; // Alterar um dado apontado por qualquer elemento que seja um ponteiro válido e que não exceda os limites do dado apontado, pois embora os elementos da matriz sejam constantes, os conteúdos apontados não o são.

// Com Matriz3, não posso fazer:
Matriz3[1][0]=sv2; // Alterar ponteiro contido em um dos elementos da matriz, mesmo que o tipo do novo valor seja compatível, pois os elementos são constantes, ainda que os dados apontados não o sejam.

// O compilador não vai alarmar, mas eu também não devo fazer com Matriz3:
l=strlen(Matriz3[2][1]); // Usar dados que não são strings (porque eu sei que não têm o byte terminador) como se fossem strings.
Matriz3[1][1][100]=c; // Exceder os limites do conteúdo apontado por um dos elementos da matriz, quer seja para gravar conteúdo...
c=Matriz3[1][1][100]; // ... quer para ler conteúdo.
Matriz3[0][0][0]=c; // Como eu sei que este elemento da matriz contém um ponteiro inválido, não posso usar tal ponteiro para gravar conteúdo...
c=Matriz3[0][0][0]; // ... nem para ler conteúdo.


// Com Matriz4, posso fazer:
pcc=Matriz4[0][0]; // Obter o valor de qualquer elemento da matriz e atribuí-lo a um ponteiro para dados constantes (mesmo tipo).
c=Matriz4[0][0][0]; // Obter um dado apontado por qualquer elemento que seja um ponteiro válido e que não exceda os limites do dado apontado.

// Com Matriz4, não posso fazer:
pc=Matriz4[0][0]; // Obter o valor de qualquer elemento da matriz e atribuí-lo a um ponteiro para dados não-constantes (tipo incompatível).
Matriz4[0][1]="Texto2"; // Alterar ponteiro contido em um dos elementos da matriz, mesmo que o tipo do novo valor seja compatível, pois os elementos são constantes, ainda que os dados apontados não o sejam.
Matriz4[1][1][0]=c; // Alterar um dado apontado por qualquer elemento, independentemente do valor do ponteiro.

// O compilador não vai alarmar, mas eu também não devo fazer com Matriz4:
l=strlen(Matriz4[2][0]); // Usar dados que não são strings (porque eu sei que não têm o byte terminador) como se fossem strings.
c=Matriz4[0][1][100]; // Exceder os limites do conteúdo apontado por um dos elementos da matriz, mesmo que somente para ler conteúdo.
c=Matriz4[2][1][0]; // Como eu sei que este elemento da matriz contém um ponteiro inválido, não posso usar tal ponteiro nem mesmo para ler conteúdo.
}


Antes de concluir, nos exemplos acima, eu uso construções semelhantes a Matriz[0]0][2], que dão a aparência de um array tridimensional. Não é o caso: o array é bidimensional, mas o elemento individual é um ponteiro, e ponteiros admitem a suposição de que as regiões de memória às quais se referem contêm não necessariamente apenas um dado do tipo apontado, mas múltiplos dados adjacentes desse mesmo tipo, e também uso do operador de indexação ([]) junto com um valor inteiro k, a fim de obter acesso ao k+1-ésimo elemento de um desses possíveis blocos de vários valores adjacentes.

----------
 O C é um pouco mais tolerante que o C++ ao usar constantes literais de strings entre aspas. No C++, o byte é sempre incluído após o último caráter entre aspas, ao passo que em C existe uma exceção para essa regra, que é no momento da declaração de um array, conforme mostra o exemplo abaixo.
char str1[6]="Teste";  // Tamanho do array é 6, suficiente para os 5 do texto mais o byte nulo. Válido em C e em C++.
char str2[]="Teste"; // Tamanho do array calculado automaticamente como 6, a partir dois 5 visíveis entre aspas, mais o nulo implícito. Válido em C e em C++.
char arr3[5]="Teste"; // Tamanho do array é 5. Válido em C, que suprime o byte nulo (sem o nulo, esse array não pode ser considerado como string!), mas ERRO em C++ por não acomodar os 6 caracteres referentes aos 5 do texto visível mais o nulo implícito.
char arr4[4]="Teste". // Tamanho do array é 4. ERRO tanto em C quanto em C++, por não acomodar nem mesmo os caracteres visíveis da constante literal entre aspas.



... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)

3. Re: Como declarar corretamente char* em C [RESOLVIDO]

Samuel Leonardo
SamL

(usa XUbuntu)

Enviado em 07/11/2021 - 11:36h

O terminador nulo é apenas para as strings dentro da matriz:
char m[3][2] isso é uma matriz de caracteres, ou, um vetor de 3 strings de tamanho 2 contando com o char nulo:
char m[3][2] = {
"1",//o compilador coloca sozinho o \0 aqui
"2",
"3",
};

Se colocar mais do que 1 char por string o compilador vai dá erro, pois o último char é reservado para o nulo.

Outro exemplo
//abaixo, uma matriz de 3 strings de tamanho no máximo 4
char m[3][4] = {
"um",//3 chars contando com o nulo
"two",//se fosse "dois" estaria errado,
"3",//não cabe aqui o "tres" ou "three", pois o último char é resevado para o \0
};

Se colocar "dois" no lugar de "two" ali, o compilador vai alertar sobre isso.


4. Re: Como declarar corretamente char* em C [RESOLVIDO]

Apprentice X
ApprenticeX

(usa Slackware)

Enviado em 12/11/2021 - 17:39h

SamL escreveu:
O terminador nulo é apenas para as strings dentro da matriz:
char m[3][2] isso é uma matriz de caracteres, ou, um vetor de 3 strings de tamanho 2 contando com o char nulo:
char m[3][2] = {
"1",//o compilador coloca sozinho o \0 aqui
"2",
"3",
};

Se colocar mais do que 1 char por string o compilador vai dá erro, pois o último char é reservado para o nulo.

Outro exemplo
//abaixo, uma matriz de 3 strings de tamanho no máximo 4
char m[3][4] = {
"um",//3 chars contando com o nulo
"two",//se fosse "dois" estaria errado,
"3",//não cabe aqui o "tres" ou "three", pois o último char é resevado para o \0
};

Se colocar "dois" no lugar de "two" ali, o compilador vai alertar sobre isso.

Obrigado SamL pela resposta, porém minha dúvida é sobre ponteiros, visto que na pergunta acima uma matriz de char usando ponteiros armazena campos que podem conter vários caracteres, enquanto uma matriz de char simples armazenaria apenas 1 cadeia de caracteres com a quantidade de caracteres informada, e seria outro tratamento possivelmente para que ela tivesse tipo 2 ou 3 campos para armazenar uma cadeia de caracteres para cada um desses campos!


5. Re: Como declarar corretamente char* em C [RESOLVIDO]

Apprentice X
ApprenticeX

(usa Slackware)

Enviado em 12/11/2021 - 17:40h

paulo1205 escreveu:
Essa disposição, por si só, já seria suficiente para mostrar por que razão não poderia ser usada a lista de inicialização {"Texto1", "", 0}, como na pergunta que você colocou num comentário no meio do código, pois ela tentaria colocar um terceiro elemento em Matriz[0], que é um array que só tem dois elementos. Se você tentar fazê-lo deve receber um erro de compilação, indicando que a lista de inicialização excedeu o tamanho do array.

Quando citei o uso do caracter terminador {"Texto1", "", 0} eu já sabia que se tivesse que usá-lo eu teria que passar char *Matriz[3][2] para char *Matriz[3][3]

paulo1205 escreveu:
Quando você levanta dúvidas sobre terminador, entendo que se refere ao bye nulo que indica o fim de uma string. Esse byte nulo é automaticamente colocado ao final da string quando você usa a notação de constantes literais entre aspas. Quando você usa, por exemplo, "Texto1" no seu código, está provocando a alocação em algum lugar da memória para sete caracteres, sendo os seis do texto que você vê e mais um para acomodar o byte terminador. De modo semelhante, uma suposta “string vazia”, indicada como "" não representa uma região de memória de tamanho zero, mas sim uma região com tamanho um, a fim de acomodar o byte nulo.

Interessante saber disso! Eu não sabia!

Os outros pontos que vc escreveu, eu vou estudá-los, montando os exemplos e olhando no gdb para entender melhor
Vou precisar analisar linha a linha do que vc escreveu pra compreender, isso levará um tempinho!
E terei que ler mais sobre ponteiros!

Obrigado pela Grande Aula dada aqui!


6. Re: Como declarar corretamente char* em C [RESOLVIDO]

Samuel Leonardo
SamL

(usa XUbuntu)

Enviado em 12/11/2021 - 17:57h


ApprenticeX escreveu:
Obrigado SamL pela resposta, porém minha dúvida é sobre ponteiros, visto que na pergunta acima uma matriz de char usando ponteiros armazena campos que podem conter vários caracteres, enquanto uma matriz de char simples armazenaria apenas 1 cadeia de caracteres com a quantidade de caracteres informada, e seria outro tratamento possivelmente para que ela tivesse tipo 2 ou 3 campos para armazenar uma cadeia de caracteres para cada um desses campos!

Ah tá, vi de novo agora, e vi que é uma matriz de ponteiros, pensei que fosse para um único ponteiro.
O delimitador nulo deve ser sempre colocado no final se você for trabalhar com strings, mas não dentro do campo da matriz:

char *m[3][64] = {
{"texto1", "texto2", "texto3"},
{"texto4", "texto5", "texto6"},
{NULL, NULL, NULL} //NULL aqui é opcional
};
//acessando as strings como uma matriz 2d:
printf("m[0][0] = %s\n", m[0][0]);
printf("m[1][1] = %s\n", m[1][1]);
printf("m[2][2] = %s\n", m[2][2]);
:
Você pode usar o NULL dentro da matriz apenas para informar que aquela posição está vazia, mas não é algo estritatemnte obrigatório, apesar de eu achar uma boa ideia iniciar com null, porque ser que você esqueça que aquela área da matriz NÃO está iniciada e então colocar em funções de manipulação de strings (da string.h, por exemplo).
Então, não há necessidade também do terminador nulo (\0) dentro da matriz, mas apenas no conteúdo da strings da matriz.
Se quiser um "terminador nulo" (okha as aspas) na matriz, você deve colocar o NULL, já que na matriz trata de ponteiros.

Acho que o Paulo pode dar uma explicação sobre isso melhor que eu.


7. Re: Como declarar corretamente char* em C [RESOLVIDO]

Apprentice X
ApprenticeX

(usa Slackware)

Enviado em 13/11/2021 - 13:17h

SamL escreveu:
O delimitador nulo deve ser sempre colocado no final se você for trabalhar com strings, mas não dentro do campo da matriz:

char *m[3][64] = {
{"texto1", "texto2", "texto3"},
{"texto4", "texto5", "texto6"},
{NULL, NULL, NULL} //NULL aqui é opcional
};
//acessando as strings como uma matriz 2d:
printf("m[0][0] = %s\n", m[0][0]);
printf("m[1][1] = %s\n", m[1][1]);
printf("m[2][2] = %s\n", m[2][2]);
:
Você pode usar o NULL dentro da matriz apenas para informar que aquela posição está vazia, mas não é algo estritatemnte obrigatório, apesar de eu achar uma boa ideia iniciar com null, porque ser que você esqueça que aquela área da matriz NÃO está iniciada e então colocar em funções de manipulação de strings (da string.h, por exemplo).

Então, não há necessidade também do terminador nulo (\0) dentro da matriz, mas apenas no conteúdo da strings da matriz.
Se quiser um "terminador nulo" (okha as aspas) na matriz, você deve colocar o NULL, já que na matriz trata de ponteiros.

Acho que o Paulo pode dar uma explicação sobre isso melhor que eu.

Obrigado por essa adição, sempre é bom saber!






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts