Como inicializar todos os membros de uma matriz para o mesmo valor?


968

Eu tenho uma grande matriz em C (não C ++, se isso faz a diferença). Eu quero inicializar todos os membros do mesmo valor.

Eu poderia jurar que uma vez soube uma maneira simples de fazer isso. Eu poderia usar memset()no meu caso, mas não existe uma maneira de fazer isso incorporada diretamente à sintaxe C?


16
Até agora, nenhuma das respostas menciona a notação inicializada designada que é viável com C99 e acima. Por exemplo: enum { HYDROGEN = 1, HELIUM = 2, CARBON = 6, NEON = 10, … };e struct element { char name[15]; char symbol[3]; } elements[] = { [NEON] = { "Neon", "Ne" }, [HELIUM] = { "Helium", "He" }, [HYDROGEN] = { "Hydrogen", "H" }, [CARBON] = { "Carbon", "C" }, … };. Se você remover as reticências , esses fragmentos serão compilados em C99 ou C11.
Jonathan Leffler

Resposta realmente de abelenky está usando designado initializer, mas não está totalmente formado código inicializar
Rob11311

memset () pode ajudar, mas depende do valor.
Nick

2
memset()discussão específica: stackoverflow.com/questions/7202411/... Eu acho que ele só funciona para 0.
Ciro Santilli郝海东冠状病六四事件法轮功

Respostas:


1239

A menos que esse valor seja 0 (nesse caso, você pode omitir parte do inicializador e os elementos correspondentes serão inicializados como 0), não há uma maneira fácil.

Não negligencie a solução óbvia:

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };

Os elementos com valores ausentes serão inicializados em 0:

int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0...

Portanto, isso inicializará todos os elementos para 0:

int myArray[10] = { 0 }; // all elements 0

No C ++, uma lista de inicialização vazia também inicializará todos os elementos para 0. Isso não é permitido com C:

int myArray[10] = {}; // all elements 0 in C++

Lembre-se de que objetos com duração de armazenamento estático serão inicializados como 0 se nenhum inicializador for especificado:

static int myArray[10]; // all elements 0

E que "0" não significa necessariamente "todos os bits-zero", portanto, usar o acima é melhor e mais portátil que memset (). (Os valores de ponto flutuante serão inicializados em +0, ponteiros para valor nulo etc.)


27
Lendo o padrão C ++, você também pode executar int array [10] = {}; para zero inicializar. Eu não tenho o padrão C para verificar se este C é válido também.
workmad3

54
Observando a seção 6.7.8 Inicialização do padrão C99, não parece que uma lista de inicializadores vazia seja permitida.
23616 Jonathan Leffler

7
O C99 possui muitos recursos interessantes para inicialização de estrutura e array; o único recurso que ele não possui (mas Fortran IV, 1966) possuía é uma maneira de repetir um inicializador específico para uma matriz.
Jonathan Leffler

8
@CetinSert: Como assim, não funciona? Faz exatamente o que esta resposta diz que deve fazer. Não faz o que o comentário no seu código diz, mas esse comentário está errado.
21413 Benjamin Lindley

9
@CetinSert: Você é o único que afirmou, naquele comentário, que todos os elementos seriam definidos como -1. Esta resposta afirma, com razão, que todos os elementos não especificados são definidos como zero. Os resultados do seu código estão de acordo com esta reivindicação.
22813 Benjamin Lindley

394

Se o seu compilador for o GCC, você poderá usar a seguinte sintaxe:

int array[1024] = {[0 ... 1023] = 5};

Confira a descrição detalhada: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html


12
E essa sintaxe causa um grande aumento no tamanho do arquivo dos binários compilados. Para N = 65536 (em vez de 1024), meus binários saltam de 15 KB para 270 KB de tamanho !!
Cetin Sert # 28/13

50
O @CetinSert Compiler precisa adicionar 65536 ints aos dados estáticos, que são 256 K - exatamente o aumento de tamanho que você observou.
qrdl

15
@CetinSert Por que devo? É um comportamento padrão do compilador, não específico para inicializadores designados. Se você inicializar estaticamente 65536 ints, int foo1 = 1, foo2 = 1, ..., foo65536 =1;terá o mesmo aumento de tamanho.
Qdl

27
melhor ainda: "int array [] = {[0 ... 1023] = 5}", o tamanho do array será automaticamente definido como 1024, mais fácil e seguro de modificar.
31813 Francois

4
@Francois ou para uma matriz 2D bool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}, embora eu não esteja certo de que seja mais legível que o formulário completo.
precisa saber é o seguinte

178

Para inicializar estaticamente uma grande matriz com o mesmo valor, sem várias copiar e colar, você pode usar macros:

#define VAL_1X     42
#define VAL_2X     VAL_1X,  VAL_1X
#define VAL_4X     VAL_2X,  VAL_2X
#define VAL_8X     VAL_4X,  VAL_4X
#define VAL_16X    VAL_8X,  VAL_8X
#define VAL_32X    VAL_16X, VAL_16X
#define VAL_64X    VAL_32X, VAL_32X

int myArray[53] = { VAL_32X, VAL_16X, VAL_4X, VAL_1X };

Se você precisar alterar o valor, precisará fazer a substituição em apenas um local.

Editar: possíveis extensões úteis

(cortesia de Jonathan Leffler )

Você pode generalizar isso facilmente com:

#define VAL_1(X) X
#define VAL_2(X) VAL_1(X), VAL_1(X)
/* etc. */

Uma variante pode ser criada usando:

#define STRUCTVAL_1(...) { __VA_ARGS__ }
#define STRUCTVAL_2(...) STRUCTVAL_1(__VA_ARGS__), STRUCTVAL_1(__VA_ARGS__)
/*etc */ 

que trabalha com estruturas ou matrizes compostas.

#define STRUCTVAL_48(...) STRUCTVAL_32(__VA_ARGS__), STRUCTVAL_16(__VA_ARGS__)

struct Pair { char key[16]; char val[32]; };
struct Pair p_data[] = { STRUCTVAL_48("Key", "Value") };
int a_data[][4] = { STRUCTVAL_48(12, 19, 23, 37) };

nomes de macro são negociáveis.


12
Eu consideraria isso apenas em casos extremos, certamente um memset é a maneira mais elegante de expressá-lo.
U0b34a0f6ae 14/10/09

47
Se os dados tiverem capacidade para ROM, o memset não poderá ser usado.
O contrato do Prof. Falken violou

9
O pré-processador irá realmente gerar o código a partir de #defines. Com dimensões de matriz maiores, o tamanho do executável aumentará. Mas definitivamente + para a idéia;)
Leonid

7
@Alcott, em computadores antigos e ainda em muitos sistemas incorporados, o código é finalmente colocado em uma EPROM ou ROM . Capacidade para ROM também passou a significar, em sistemas embarcados, "código colocado em flash", porque tem as mesmas implicações, a saber, que a memória não pode ser escrita em tempo de execução. Ou seja, memset ou qualquer outra instrução para atualizar ou alterar a memória não pode ser usada. As constantes, no entanto, podem ser expressas e atualizadas ou editadas em ROM antes do início do programa.
O contrato do Prof. Falken violou

4
@ u0b34a0f6ae: Lembre-se de que você também pode usar esse método se VAL_1Xnão for um único inteiro, mas uma lista. Como estados Amigable, este também é o caminho a seguir para sistemas incorporados nos quais você deseja definir os valores init de uma memória EEPROM ou Flash. Nos dois casos, você não pode usar memset().
Martin Scharrer

63

Se você deseja garantir que todos os membros da matriz sejam explicitamente inicializados, apenas omita a dimensão da declaração:

int myArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

O compilador deduzirá a dimensão da lista de inicializadores. Infelizmente, para matrizes multidimensionais, apenas a dimensão mais externa pode ser omitida:

int myPoints[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };

está bem, mas

int myPoints[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };

não é.


isto está correto? int myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
Praveen Gowda IV

10
Não. Você está omitindo a dimensão mais interna, o que não é permitido. Isso dará um erro do compilador.
Frank Szczerba

4
Os inicializadores e a inferência de comprimento foram introduzidos em C99.
Palec

3
@Palec: Não - há inferência de comprimento em C desde os dias do C pré-padrão (desde a publicação da K&R 1st Edition, e provavelmente um tempo antes disso). Os inicializadores designados eram novos no C99, mas isso não está usando inicializadores designados.
27617 Jonathan-Leffler-

53

Eu vi algum código que usava esta sintaxe:

char* array[] = 
{
    [0] = "Hello",
    [1] = "World"
};   

Onde isso se torna particularmente útil é se você estiver criando uma matriz que usa enumerações como índice:

enum
{
    ERR_OK,
    ERR_FAIL,
    ERR_MEMORY
};

#define _ITEM(x) [x] = #x

char* array[] = 
{
    _ITEM(ERR_OK),
    _ITEM(ERR_FAIL),
    _ITEM(ERR_MEMORY)
};   

Isso mantém as coisas em ordem, mesmo que você escreva alguns valores enum fora de ordem.

Mais sobre esta técnica pode ser encontrada aqui e aqui .


8
Essa é a sintaxe do inicializador C99, já abordada por algumas das outras respostas. Você poderia utilmente fazer a declaração char const *array[] = { ... };ou até mesmo char const * const array[] = { ... };, não é?
31812 Jonathan Leffler

22
int i;
for (i = 0; i < ARRAY_SIZE; ++i)
{
  myArray[i] = VALUE;
}

Eu acho que isso é melhor do que

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5...

caso o tamanho da matriz seja alterado.


12
Para o registro, que é basicamente apenas um mais lento, mais detalhado versãomemset(myArray, VALUE, ARRAY_SIZE);
Benson

18
Como você usaria o memset para inicializar uma matriz int para um valor maior que 255? O memset só funciona se a matriz tiver tamanho de bytes.
Matt

21
@ Benson: Você não pode substituir o código acima por memset em plataformas onde sizeof (int)> sizeof (char). Tente.
ChrisWue

13

Você pode fazer toda a coisa do inicializador estático, conforme detalhado acima, mas pode ser uma chatice quando o tamanho da sua matriz muda (quando sua matriz embiggens, se você não adicionar os inicializadores extras apropriados, obterá lixo).

O memset fornece um hit de tempo de execução para o trabalho, mas nenhum hit de tamanho de código feito corretamente é imune a alterações no tamanho da matriz. Eu usaria essa solução em quase todos os casos em que a matriz era maior do que, digamos, algumas dezenas de elementos.

Se fosse realmente importante que a matriz fosse declarada estaticamente, eu escreveria um programa para escrever o programa para mim e fazer parte do processo de compilação.


Você poderia adicionar algum exemplo sobre o uso de memsetpara inicializar a matriz?
Sopalajo de Arrierez

8

Aqui está outra maneira:

static void
unhandled_interrupt(struct trap_frame *frame, int irq, void *arg)
{
    //this code intentionally left blank
}

static struct irqtbl_s vector_tbl[XCHAL_NUM_INTERRUPTS] = {
    [0 ... XCHAL_NUM_INTERRUPTS-1] {unhandled_interrupt, NULL},
};

Vejo:

Extensões C

Unidades designadas

Em seguida, faça a pergunta: quando alguém pode usar extensões C?

O exemplo de código acima está em um sistema incorporado e nunca verá a luz de outro compilador.


6

Para inicializar tipos de dados 'normais' (como matrizes int), você pode usar a notação de colchete, mas zerará os valores após o último se ainda houver espaço na matriz:

// put values 1-8, then two zeroes
int list[10] = {1,2,3,4,5,6,7,8};

5

Se a matriz for int ou qualquer coisa com o tamanho de int ou o tamanho do seu padrão de mem se encaixar vezes exatas em um int (ou seja, todos os zeros ou 0xA5A5A5A5), a melhor maneira é usar memset () .

Caso contrário, chame memcpy () em um loop para mover o índice.


5

Uma resposta levemente explícita; escreva a declaração

array = initial_value

na sua linguagem favorita de capacidade de array (a minha é Fortran, mas existem muitas outras) e vincule-a ao seu código C. Você provavelmente desejaria agrupá-lo para ser uma função externa.


4

Existe uma maneira rápida de inicializar uma matriz de qualquer tipo com determinado valor. Funciona muito bem com matrizes grandes. O algoritmo é o seguinte:

  • inicialize o primeiro elemento da matriz (maneira usual)
  • copiar parte que foi ajustada em parte que não foi ajustada, dobrando o tamanho a cada próxima operação de cópia

Para a matriz de 1 000 000elementos int, é 4 vezes mais rápido que a inicialização normal do loop (i5, 2 núcleos, 2,3 GHz, memória 4GiB, 64 bits):

loop runtime 0.004248 [seconds]

memfill() runtime 0.001085 [seconds]


#include <stdio.h>
#include <time.h>
#include <string.h>
#define ARR_SIZE 1000000

void memfill(void *dest, size_t destsize, size_t elemsize) {
   char   *nextdest = (char *) dest + elemsize;
   size_t movesize, donesize = elemsize;

   destsize -= elemsize;
   while (destsize) {
      movesize = (donesize < destsize) ? donesize : destsize;
      memcpy(nextdest, dest, movesize);
      nextdest += movesize; destsize -= movesize; donesize += movesize;
   }
}    
int main() {
    clock_t timeStart;
    double  runTime;
    int     i, a[ARR_SIZE];

    timeStart = clock();
    for (i = 0; i < ARR_SIZE; i++)
        a[i] = 9;    
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("loop runtime %f [seconds]\n",runTime);

    timeStart = clock();
    a[0] = 10;
    memfill(a, sizeof(a), sizeof(a[0]));
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("memfill() runtime %f [seconds]\n",runTime);
    return 0;
}

2
Desculpe, mas isso não é verdade. Talvez você tenha esquecido de ativar a otimização de compilação durante seus testes (testado no modo de depuração?). Se eu testar isso, o loop é quase sempre 50% mais rápido que o memfill ('sempre' devido a alguns tremores de carga na minha máquina). E usando memset (a, 0, sizeof (a)); é duas vezes mais rápido que o preenchimento de loop.
RS1980 17/03/19

2
Como em qualquer código de benchmarking, você precisa ser extremamente cuidadoso. Adicionar um loop para executar o código de temporização 10 vezes (e dobrar o tamanho da matriz para 20M) mostra - para mim, rodando em um MacBook Pro com o macOS Sierra 10.12.3 e usando o GCC 6.3.0 - que na primeira vez, usando o loop leva cerca de 4600 µs, enquanto o memfill()código leva cerca de 1200 µs. No entanto, nas iterações subsequentes, o loop leva cerca de 900-1000 µs enquanto o memfill()código leva 1000-1300 µs. A primeira iteração provavelmente é afetada pelo tempo para preencher o cache. Inverta os testes e memfill()é lento pela primeira vez.
Jonathan Leffler

2

Ninguém mencionou a ordem do índice para acessar os elementos da matriz inicializada. Meu código de exemplo fornecerá um exemplo ilustrativo.

#include <iostream>

void PrintArray(int a[3][3])
{
    std::cout << "a11 = " << a[0][0] << "\t\t" << "a12 = " << a[0][1] << "\t\t" << "a13 = " << a[0][2] << std::endl;
    std::cout << "a21 = " << a[1][0] << "\t\t" << "a22 = " << a[1][1] << "\t\t" << "a23 = " << a[1][2] << std::endl;
    std::cout << "a31 = " << a[2][0] << "\t\t" << "a32 = " << a[2][1] << "\t\t" << "a33 = " << a[2][2] << std::endl;
    std::cout << std::endl;
}

int wmain(int argc, wchar_t * argv[])
{
    int a1[3][3] =  {   11,     12,     13,     // The most
                        21,     22,     23,     // basic
                        31,     32,     33  };  // format.

    int a2[][3] =   {   11,     12,     13,     // The first (outer) dimension
                        21,     22,     23,     // may be omitted. The compiler
                        31,     32,     33  };  // will automatically deduce it.

    int a3[3][3] =  {   {11,    12,     13},    // The elements of each
                        {21,    22,     23},    // second (inner) dimension
                        {31,    32,     33} };  // can be grouped together.

    int a4[][3] =   {   {11,    12,     13},    // Again, the first dimension
                        {21,    22,     23},    // can be omitted when the 
                        {31,    32,     33} };  // inner elements are grouped.

    PrintArray(a1);
    PrintArray(a2);
    PrintArray(a3);
    PrintArray(a4);

    // This part shows in which order the elements are stored in the memory.
    int * b = (int *) a1;   // The output is the same for the all four arrays.
    for (int i=0; i<9; i++)
    {
        std::cout << b[i] << '\t';
    }

    return 0;
}

A saída é:

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

11      12      13      21      22      23      31      32      33

4
<iostream>não é válido , Cpois std::cout, std::cinetc faz parte do std::namespacee Cnão é compatível namespaces. Tente usar <stdio.h>para em printf(...)vez disso.
Francis Cugler

2

Cortando toda a conversa, a resposta curta é que, se você ativar a otimização em tempo de compilação, não fará melhor que isso:

int i,value=5,array[1000]; 
for(i=0;i<1000;i++) array[i]=value; 

Bônus adicionado: o código é realmente legível :)


7
A pergunta especificamente solicitada para inicialização. Isso explicitamente não é inicialização, mas atribuição feita após a inicialização. Isso pode ser feito imediatamente, mas ainda não é a inicialização.
Andy

Inteiramente útil para uma grande tabela de pesquisa estática dentro de uma função chamada várias vezes.
Martin Bonner apoia Monica

... não lembre-se de que as tabelas de pesquisa estática dentro das funções fazem parte da pergunta original - mantenha-a simples. Dito isto, a @Community provavelmente acertou em cheio.
JWDN 16/02/19

1
  1. Se sua matriz for declarada como estática ou global, todos os elementos na matriz já terão o valor padrão padrão 0.
  2. Alguns compiladores configuram o padrão da matriz como 0 no modo de depuração.
  3. É fácil definir o padrão como 0: int array [10] = {0};
  4. No entanto, para outros valores, você usa memset () ou loop;

exemplo: matriz int [10]; memset (matriz, -1, 10 * sizeof (int));


0
#include<stdio.h>
int main(){
int i,a[50];
for (i=0;i<50;i++){
    a[i]=5;// set value 5 to all the array index
}
for (i=0;i<50;i++)
printf("%d\n",a[i]);
   return 0;
}

Ele dará o / p 5 5 5 5 5 5 ...... até o tamanho de toda a matriz


0

Sei que o usuário Tarskirespondeu a essa pergunta de maneira semelhante, mas adicionei mais alguns detalhes. Perdoe parte do meu C porque estou um pouco enferrujado, pois estou mais inclinado a querer usar o C ++, mas aqui está.


Se você souber o tamanho da matriz antes do tempo ...

#include <stdio.h>

typedef const unsigned int cUINT;
typedef unsigned int UINT;

cUINT size = 10;
cUINT initVal = 5;

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal );
void printArray( UINT* myArray ); 

int main() {        
    UINT myArray[size]; 
    /* Not initialized during declaration but can be
    initialized using a function for the appropriate TYPE*/
    arrayInitializer( myArray, size, initVal );

    printArray( myArray );

    return 0;
}

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal ) {
    for ( UINT n = 0; n < size; n++ ) {
        myArray[n] = initVal;
    }
}

void printArray( UINT* myArray ) {
    printf( "myArray = { " );
    for ( UINT n = 0; n < size; n++ ) {
        printf( "%u", myArray[n] );

        if ( n < size-1 )
            printf( ", " );
    }
    printf( " }\n" );
}

Existem algumas ressalvas acima; uma é que UINT myArray[size];não é inicializada diretamente na declaração; no entanto, o próximo bloco de código ou chamada de função inicializa cada elemento da matriz com o mesmo valor desejado. A outra ressalva é que você teria que escrever um initializing functionpara cada um dos quais typevocê apoiará e também teria que modificar a printArray()função para suportar esses tipos.


Você pode tentar esse código com um complier online encontrado aqui .


0

Para inicialização atrasada (isto é, inicialização do construtor do membro da classe), considere:

int a[4];

unsigned int size = sizeof(a) / sizeof(a[0]);
for (unsigned int i = 0; i < size; i++)
  a[i] = 0;

0

Eu sei que a pergunta original menciona explicitamente C e não C ++, mas se você (como eu) veio aqui procurando uma solução para matrizes C ++, aqui está um truque:

Se o seu compilador suportar expressões de dobra , você poderá usar a mágica do modelo e std::index_sequencegerar uma lista de inicializadores com o valor desejado. E você pode equilibrar constexpre se sentir como um chefe:

#include <array>

/// [3]
/// This functions's only purpose is to ignore the index given as the second
/// template argument and to always produce the value passed in.
template<class T, size_t /*ignored*/>
constexpr T identity_func(const T& value) {
    return value;
}

/// [2]
/// At this point, we have a list of indices that we can unfold
/// into an initializer list using the `identity_func` above.
template<class T, size_t... Indices>
constexpr std::array<T, sizeof...(Indices)>
make_array_of_impl(const T& value, std::index_sequence<Indices...>) {
    return {identity_func<T, Indices>(value)...};
}

/// [1]
/// This is the user-facing function.
/// The template arguments are swapped compared to the order used
/// for std::array, this way we can let the compiler infer the type
/// from the given value but still define it explicitly if we want to.
template<size_t Size, class T>
constexpr std::array<T, Size> 
make_array_of(const T& value) {
    using Indices = std::make_index_sequence<Size>;
    return make_array_of_impl(value, Indices{});
}

// std::array<int, 4>{42, 42, 42, 42}
constexpr auto test_array = make_array_of<4/*, int*/>(42);
static_assert(test_array[0] == 42);
static_assert(test_array[1] == 42);
static_assert(test_array[2] == 42);
static_assert(test_array[3] == 42);
// static_assert(test_array[4] == 42); out of bounds

Você pode dar uma olhada no código no trabalho (na Wandbox)


-1

Não vejo requisitos na pergunta, portanto a solução deve ser genérica: inicialização de uma matriz multidimensional possivelmente não especificada, construída a partir de elementos de estrutura não especificados com um valor inicial de membro:

#include <string.h> 

void array_init( void *start, size_t element_size, size_t elements, void *initval ){
  memcpy(        start,              initval, element_size              );
  memcpy( (char*)start+element_size, start,   element_size*(elements-1) );
}

// testing
#include <stdio.h> 

struct s {
  int a;
  char b;
} array[2][3], init;

int main(){
  init = (struct s){.a = 3, .b = 'x'};
  array_init( array, sizeof(array[0][0]), 2*3, &init );

  for( int i=0; i<2; i++ )
    for( int j=0; j<3; j++ )
      printf("array[%i][%i].a = %i .b = '%c'\n",i,j,array[i][j].a,array[i][j].b);
}

Resultado:

array[0][0].a = 3 .b = 'x'
array[0][1].a = 3 .b = 'x'
array[0][2].a = 3 .b = 'x'
array[1][0].a = 3 .b = 'x'
array[1][1].a = 3 .b = 'x'
array[1][2].a = 3 .b = 'x'

EDIT: start+element_sizealterado para(char*)start+element_size


1
Eu duvido que isso seja ou não uma solução. Não tenho certeza se sizeof(void)é válido.
31720 Chris Lutz

3
Isso não funciona. Somente os dois primeiros são inicializados, o restante não é inicializado. Estou usando o GCC 4.0 no Mac OS X 10.4.
dreamlax

Isso chama um comportamento indefinido porque os dados de origem no segundo se memcpy()sobrepõem ao espaço de destino. Com uma implementação ingênua de memcpy(), pode funcionar, mas não é necessário que o sistema o faça funcionar.
Jonathan Leffler

-1

De volta ao dia (e não estou dizendo que é uma boa ideia), definiríamos o primeiro elemento e depois:

memcpy (&element [1], &element [0], sizeof (element)-sizeof (element [0]);

Nem tenho certeza de que funcionaria mais (isso dependeria da implementação do memcpy), mas funciona copiando repetidamente o elemento inicial para o próximo - até funciona para matrizes de estruturas.


Isso não funcionará de maneira confiável. IMHO, o Padrão deveria ter fornecido funções semelhantes, memcpymas especificadas de baixo para cima ou de cima para baixo em caso de sobreposição, mas não.
supercat 30/01

Como eu disse, foi apenas algo que fizemos que não funcionaria de maneira confiável, mas, naquela época, estávamos mais focados em eficiência do que em evitar recursos não documentados. Embora seja mais eficiente copiar a memória para a frente, não há nada na especificação que diga que ela não pode ser copiada para trás, em uma ordem aleatória ou dividida em vários threads. O memmove () fornece a capacidade de copiar sem conflitos.
Mike

Isso é equivalente ao código em outra resposta - e falho. Usar memmove()não o faz funcionar.
Jonathan Leffler

-2

Se você quer dizer em paralelo, acho que o operador de vírgula quando usado em conjunto com uma expressão pode fazer isso:

a[1]=1, a[2]=2, ..., a[indexSize]; 

ou se você quer dizer em uma única construção, você pode fazer isso em um loop for:

for(int index = 0, value = 10; index < sizeof(array)/sizeof(array[0]); index++, value--)
  array[index] = index;

// Observe que o operador de vírgula em uma lista de argumentos não é o operador paralelo descrito acima;

Você pode inicializar uma decleração de matriz:

array[] = {1, 2, 3, 4, 5};

Você pode fazer uma chamada para malloc / calloc / sbrk / alloca / etc para alocar uma região fixa de armazenamento para um objeto:

int *array = malloc(sizeof(int)*numberOfListElements/Indexes);

e acesse os membros por:

*(array + index)

Etc.


O operador de vírgula garante nominalmente a avaliação da esquerda para a direita. Se não houver efeitos colaterais nas expressões, talvez seja possível paralelizar as operações, mas seria incomum um compilador fazer isso.
Jonathan Leffler
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.