7

In higher level languages I would be able something similar to this example in C and it would be fine. However, when I compile this C example it complains bitterly. How can I assign new arrays to the array I declared?

int values[3];

if(1)
   values = {1,2,3};

printf("%i", values[0]);

Thanks.

1

9 Answers 9

12

You can only do multiple assignment of the array, when you declare the array:

int values[3] = {1,2,3};

After declaration, you'll have to assign each value individually, i.e.

if (1) 
{
  values[0] = 1;
  values[1] = 2;
  values[2] = 3;
}

Or you could use a loop, depending on what values you want to use.

if (1)
{
  for (i = 0 ; i < 3 ; i++)
  { 
    values[i] = i+1;
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

This works for 3 values, but what if I had an array with 50 values?
Then you would use a loop, or you would memmove/memcpy like @hacker suggests in another answer.
memcpy seems tidiest. Thanks for your help.
8

In C99, using compound literals, you could do:

memcpy(values, (int[3]){1, 2, 3}, sizeof(int[3]));

or

int* values = (int[3]){1, 2, 3};

7 Comments

+1; keep in mind that in the latter case, the array will have automatic storage duration, ie returning it from a function will get you eaten by a grue
Christoph, would that mean that memmoveing from such an array would involve first initializing it in automatic storage and then copying it over?
@hacker: in priciple, yes, in practice, the compiler will optimize it away (for gcc, -O1 is enough)
On the other hand, are you sure it is really automatic storage? Isn't this similar to string literals? Or would using const keyword make it behave the way string literals would?
@hacker: yes, const compound literals may be shared the same way strings are (this is an implementation detail and has no bearing on language semantics); non-const literals are guaranteed to be distinct on each entry to the enclosing block
|
4
 //compile time initialization
 int values[3] = {1,2,3};

//run time assignment
 value[0] = 1;
 value[1] = 2;
 value[2] = 3;

Comments

3

you can declare static array with data to initialize from:

static int initvalues[3] = {1,2,3};
…
if(1)
    memmove(values,initvalues,sizeof(values));

6 Comments

Can I not do memmove(values,{1,2,3},sizeof(values)); ?
I think you could: memmove(values, (int[3]){1,2,3}, sizeof(int[3])); See my answer below.
There's no need to use memmove over memcpy here - the arrays definitely do not overlap.
Why do you think I used memmove "over memcpy"? I just used memmove. ;-)
@Michael: what @caf meant is that in the given scenario there's no need to move memory because source and dest don't overlap. That way, memcpy may be slightly faster. See this stackoverflow.com/questions/1201319/…
|
1
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>

int *setarray(int *ar,char *str)
{
    int offset,n,i=0;
    while (sscanf(str, " %d%n", &n, &offset)==1)
    {
        ar[i]=n;
        str+=offset;
        i+=1;
    }
    return ar;
}

int *setarray2(int *ar,int num,...)
{
   va_list valist;
   int i;
   va_start(valist, num);

   for (i = 0; i < num; i++) 
        ar[i] = va_arg(valist, int);
   va_end(valist);
   return ar;
}

int main()
{
    int *size=malloc(3*sizeof(int*)),i;
    setarray(size,"1 2 3");

    for(i=0;i<3;i++)
        printf("%d\n",size[i]);

    setarray2(size,3 ,4,5,6);
    for(i=0;i<3;i++)
        printf("%d\n",size[i]);

    return 0;
}

3 Comments

you can also loop sscanf from a function then return the array
Welcome to Stack Overflow. Please read the About page soon. When you answer a question over 6 years after it is asked (and it has up-voted and accepted answers), you must have something distinctive to add — a novel approach, or perhaps the product has changed since the original answers were given. Fortunately for you, none of the other answers suggests parsing a string representation of the array values — so that much is OK. I'm not sure it is a good mechanism, but it is different. Your call to malloc() is not allocating enough space on any machine where sizeof(char) != sizeof(int).
edited malloc, if using strings does not work, you can also use the functions from stdarg.h
0

It is also possible to hide the memcpy by using the compiler's block copy of structs. It makes the code ugly because of all the .i and i: but maybe it solves your specific problem.

typedef struct {
    int i[3];
} inta;

int main()
{
    inta d = {i:{1, 2, 3}};

    if (1)
        d = (inta){i:{4, 5, 6}};

    printf("%d %d %d\n", d.i[0], d.i[1], d.i[2]);

    return 0;
}

Comments

0

There is also this... :)

char S[16]="";
strncpy(S,"Zoodlewurdle...",sizeof(S)-1);

Test what happens if you declare S[8] or S[32], to see why this is so effective.

I wrote my own string functions based on the logic of OpenBSD's strlcpy, aimed at ensuring a terminator byte MUST exist in the event of overflow, and standard strncpy won't do this so you have to watch carefully how you use it.

The method above is effective because the ="" at declaration ensures 0 bytes throughout, and sizeof(S)-1 ensures that if you overdo the quoted string passed to strncpy, you get truncation and no violation of the last 0 byte, so this is safe against overflow now, AND on accessing the string later. I aimed this at ANSI C so it ought to be safe anywhere.

2 Comments

I realise that this is a string, not an array of integers, but there may be a way to translate the method accordingly, without having to write your own iteration code.
strncpy is to character arrays as ___ is to integer arrays?
0

I would post this as a comment, but I don't have enough reputation. Another (perhaps dirty) way of initializing an array is to wrap it in a struct.

#include <stdio.h>

struct wrapper { int array[3]; };

int main(){
    struct wrapper a;
    struct wrapper b = {{1, 2, 3}};

    a = b;

    printf("%i %i %i", a.array[0], a.array[1], a.array[2]);

    return 0;
}

Comments

-1

This works and optimizes better under gcc with -O3 (the compiler completely removes the code), whereas the memcpy forces the memory to be copied in all cases.

template <typename Array>
struct inner
{
    Array x;
};


template <typename Array>
void assign(Array& lhs, const Array& rhs)
{
    inner<Array>& l( (inner<Array>&)(lhs));
    const inner<Array>& r( (inner<Array>&)(rhs));
    l = r;
}

int main()
{
    int x[100];
    int y[100];

    assign(x, y);
}

1 Comment

The question is tagged C, not C++. This answer is C++, and completely invalid in C.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.