Inicializando o array 2D inteiro com um valor

Com a seguinte declaração

int array[ROW][COLUMN]={0}; 

Eu recebo o array com todos os zeros, mas com o seguinte

 int array[ROW][COLUMN]={1}; 

Eu não obtenho o array com todos os valores. O valor padrão ainda é 0.

Por que esse comportamento e como posso inicializar com todos os 1?

EDIT: Acabei de entender que usando memset com valor como 1, irá definir cada byte como 1 e, portanto, o valor real de cada célula da matriz não será 1, mas 16843009 . Como configuro para 1?

Você obtém esse comportamento, porque int array [ROW][COLUMN] = {1}; não significa “definir todos os itens para um”. Deixe-me tentar explicar como isso funciona passo a passo.

A maneira explícita e clara de inicializar seu array seria assim:

 #define ROW 2 #define COLUMN 2 int array [ROW][COLUMN] = { {0, 0}, {0, 0} }; 

No entanto, C permite que você deixe de fora alguns dos itens em uma matriz (ou struct / union). Você poderia, por exemplo, escrever:

 int array [ROW][COLUMN] = { {1, 2} }; 

Isso significa, inicializar os primeiros elementos para 1 e 2, e o resto dos elementos “como se tivessem duração de armazenamento estático”. Existe uma regra em C dizendo que todos os objects de duração de armazenamento estático, que não são explicitamente inicializados pelo programador, devem ser configurados para zero.

Portanto, no exemplo acima, a primeira linha é definida como 1,2 e a próxima como 0,0, já que não fornecemos nenhum valor explícito.

Em seguida, há uma regra em C permitindo o estilo lax cinta. O primeiro exemplo poderia também ser escrito como

 int array [ROW][COLUMN] = {0, 0, 0, 0}; 

embora, claro, isso seja um estilo ruim, é mais difícil de ler e entender. Mas esta regra é conveniente, porque nos permite escrever

 int array [ROW][COLUMN] = {0}; 

o que significa: “inicializar a primeira coluna na primeira linha para 0, e todos os outros itens como se tivessem duração de armazenamento estático, ou seja, defini-los para zero.”

portanto, se você tentar

 int array [ROW][COLUMN] = {1}; 

significa “inicializar a primeira coluna na primeira linha como 1 e definir todos os outros itens como zero”.

Se você quiser inicializar a matriz para -1 então você pode usar o seguinte,

 memset(array, -1, sizeof(array[0][0]) * row * count) 

Mas isso só funcionará 0 e -1

 int array[ROW][COLUMN]={1}; 

Isso inicializa apenas o primeiro elemento para 1. Todo o resto recebe um 0.

No primeiro caso, você está fazendo o mesmo – inicializando o primeiro elemento como 0, e o restante é padronizado como 0.

O motivo é simples: para uma matriz, o compilador inicializará todos os valores que você não especificar com 0.

Com uma matriz char você pode usar memset para definir cada byte, mas isso geralmente não funcionará com uma matriz int (embora seja bom para 0).

Um loop geral for fazer isso rapidamente:

 for (int i = 0; i < ROW; i++) for (int j = 0; j < COLUMN; j++) array[i][j] = 1; 

Ou possivelmente mais rápido (dependendo do compilador)

 for (int i = 0; i < ROW*COLUMN; i++) *((int*)a + i) = 1; 

Observe que o GCC possui uma extensão para a notação inicializadora designada , que é muito útil para o contexto. Também é permitido pelo clang sem comentários (em parte porque tenta ser compatível com o GCC).

A notação de extensão permite usar ... para designar um intervalo de elementos a serem inicializados com o seguinte valor. Por exemplo:

 #include  enum { ROW = 5, COLUMN = 10 }; int array[ROW][COLUMN] = { [0 ... ROW-1] = { [0 ... COLUMN-1] = 1 } }; int main(void) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COLUMN; j++) printf("%2d", array[i][j]); putchar('\n'); } return 0; } 

A saída é, sem surpresa:

  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 

Note que o Fortran 66 (Fortran IV) teve contagens repetidas para inicializadores para matrizes; Sempre me pareceu estranho que C não os tenha recebido quando inicializadores designados foram adicionados ao idioma. E Pascal usa a notação 0..9 para designar o intervalo de 0 a 9 inclusive, mas C não usa .. como um token, então não é surpresa que não tenha sido usado.

Note que os espaços em torno da ... notação são essencialmente obrigatórios; se eles estiverem anexados a números, o número será interpretado como um número de ponto flutuante. Por exemplo, 0...9 seria tokenizado como 0. . , . , .9 e números de ponto flutuante não são permitidos como índices de matriz. Com as constantes nomeadas, ...ROW-1 não causaria problemas, mas é melhor entrar nos hábitos seguros.


Adenda:

Observo de passagem que o GCC 7.3.0 rejeita:

 int array[ROW][COLUMN] = { [0 ... ROW-1] = { [0 ... COLUMN-1] = { 1 } } }; 

onde há um conjunto extra de chaves ao redor do inicializador escalar 1 ( error: braces around scalar initializer [-Werror] ). Não tenho certeza se isso é correto, já que você pode especificar normalmente chaves em torno de um escalar em int a = { 1 }; , que é explicitamente permitido pelo padrão. Não tenho certeza se está incorreto também.

Eu também me pergunto se uma notação melhor seria [0]...[9] - isso não é ambíguo, não pode ser confundido com nenhuma outra syntax válida e evita confusão com números de ponto flutuante.

 int array[ROW][COLUMN] = { [0]...[4] = { [0]...[9] = 1 } }; 

Talvez o comitê de padrões considerasse isso?