سؤال

لدي مجموعة كبيرة في ج (وليس C++ إذا كان هذا يحدث فرقا).أريد أن تهيئة جميع الأعضاء على نفس القيمة.أقسم كنت أعرف طريقة بسيطة للقيام بذلك.يمكنني استخدام memset() في حالتي, ولكن ليس هناك طريقة للقيام بذلك هو أن يبنى الحق في C syntax ؟

هل كانت مفيدة؟

المحلول

وإذا لم هذه القيمة هي 0 (في هذه الحالة يمكنك حذف جزء من مهيئ وسيتم تهيئة العناصر المناظرة إلى 0)، وليس هناك طريقة سهلة.

لا تغفل حل واضح، على الرغم من:

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

وسيتم تهيئة عناصر مع القيم المفقودة إلى 0:

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

وحتى هذا سوف تهيئة كل العناصر إلى 0:

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

في C ++، سوف قائمة التهيئة فارغة أيضا تهيئة كل عنصر إلى 0. هذا هو href="https://stackoverflow.com/a/17589839"> باستخدام C:

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

وتذكر أن الكائنات مع مدة التخزين الثابتة وتهيئة إلى 0 إذا لم يتم تحديد مهيئ:

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

وأن "0" لا يعني بالضرورة "كل بت من الصفر"، وذلك باستخدام ما سبق هو أفضل وأكثر المحمولة من memset (). (العائمة القيم نقطة سيكون تهيئة إلى +0، مؤشرات إلى قيمة فارغة، الخ.)

نصائح أخرى

لتهيئة ثابت مجموعة كبيرة بنفس القيمة، دون متعددة النسخ واللصق، يمكنك استخدام وحدات الماكرو:

#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 };

إذا كنت بحاجة إلى تغيير قيمة، ما عليك القيام به بتغيير في مكان واحد فقط.

تحرير: من الممكن ملحقات مفيدة

و(من باب المجاملة جوناثان ليفلر )

ويمكنك بسهولة تعميم هذا مع:

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

ويمكن إنشاء المتغير باستخدام:

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

والذي يعمل مع الهياكل أو صفائف المجمع.

#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) };

وأسماء ماكرو قابلة للتفاوض.

إذا كنت تريد التأكد من أن كل عضو من أعضاء مجموعة يتم تهيئة صراحة، فقط تجاهل البعد عن إعلان:

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

والمترجم سوف نستنتج البعد من قائمة مهيئ. للأسف، لالمصفوفات متعددة الأبعاد فقط البعد الأبعد قد تكون أغفلت:

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

وعلى ما يرام، ولكن

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

وليس

ورأيت بعض التعليمات البرمجية التي تستخدم بناء الجملة التالي:

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

وحيث يصبح من المفيد بشكل خاص هو إذا كنت تريد أن تجعل مجموعة يستخدم تتضمن التعدادات كما الفهرس:

enum
{
    ERR_OK,
    ERR_FAIL,
    ERR_MEMORY
};

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

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

وهذا يبقي الامور في النظام، حتى لو كنت يحدث لكتابة بعض من تعداد القيم من النظام.

والمزيد من المعلومات حول هذه التقنية يمكن العثور على هنا و هنا .

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

وأعتقد أن هذا هو أفضل من

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

وطارئ حجم التغييرات صفيف.

ويمكنك أن تفعل الشيء كله ثابت شيء مهيئ كما هو موضح أعلاه، ولكنه يمكن أن يكون المشكله الحقيقية عندما التغييرات حجم مجموعة (عندما embiggens مجموعة الخاص بك، إذا كنت لا إضافة المهيآت إضافية مناسبة تحصل القمامة).

وmemset يعطيك ضربة وقت للقيام بهذا العمل، ولكن لا يوجد رمز حجم ضرب الحق في القيام به هو في مأمن من التغييرات حجم المصفوفة. وأود أن استخدام هذا الحل في جميع الحالات تقريبا عندما كانت مجموعة أكبر من، مثلا، بضع عشرات من العناصر.

إذا كان من المهم حقا أن مجموعة تم الإعلان بشكل ثابت، فما استقاموا لكم فاستقيموا كتابة برنامج لكتابة البرنامج بالنسبة لي، وجعلها جزءا من عملية الإنشاء.

وهنا طريقة أخرى:

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},
};

وانظر:

C-الامتدادات

والمعينة inits

وثم نطرح هذا السؤال: متى يمكن استخدام واحد ملحقات C

ونموذج التعليمات البرمجية أعلاه هو في نظام جزءا لا يتجزأ من ولن ترى النور من مترجم آخر.

لتهيئة أنواع البيانات "العادية" (مثل المصفوفات الباحث)، يمكنك استخدام رمز براكيت، لكنه لن الصفر القيم بعد آخر إذا كان لا يزال هناك مساحة في مجموعة:

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

وA قليلا اللسان في خده الجواب. كتابة بيان

array = initial_value

وفي المفضلة لديك لغة مجموعة قادرة (الألغام هو فورتران، ولكن هناك العديد من الآخرين)، وربطه إلى رمز C الخاص بك. ربما كنت ترغب في الانتهاء من ذلك أن تكون وظيفة الخارجية.

هناك طريقة سريعة إلى تهيئة مجموعة من أي نوع مع إعطاء قيمة.أنه يعمل بشكل جيد جدا مع صفائف كبيرة.الخوارزمية هي كما يلي:

  • تهيئة العنصر الأول من الصفيف (الطريقة المعتادة)
  • نسخ الجزء الذي تم تعيين إلى الجزء الذي لم يتم تعيين مضاعفة حجم مع كل عملية نسخ

بالنسبة 1 000 000 عناصر int مجموعة 4 مرات أسرع من العادي حلقة التهيئة (i5, 2 النوى 2.3 غيغاهرتز ، 4GiB الذاكرة 64 بت):

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;
}

لقد ذكر أحد على ترتيب فهرس للوصول إلى عناصر مجموعة تهيئته. سوف بلدي على سبيل المثال كود تعطي مثالا توضيحيا لذلك.

#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;
}

والإخراج هو:

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

وقطع من خلال جميع الثرثرة، والجواب القصير هو أنه إذا قمت بتشغيل الأمثل في وقت الترجمة فلن نفعل ما هو أفضل من هذا:

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

وأضاف المكافأة: هو رمز مقروءا في الواقع:)

  1. إذا كان الصفيف الخاص بك هو أعلن ثابتة أو عالمية ، كل العناصر في مجموعة بالفعل الافتراضي القيمة الافتراضية 0.
  2. بعض المجمعين مجموعة مجموعة الافتراضي إلى 0 في وضع التصحيح.
  3. فمن السهل أن تعيين الافتراضي إلى 0 :الباحث مجموعة[10] = {0};
  4. ومع ذلك ، من أجل قيم أخرى ، يجب استخدام memset() أو حلقة ؛

على سبيل المثال:الباحث مجموعة[10];memset(مجموعة -1, 10 *sizeof(int));

#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;
}

وسوف يعطي س / ص 5 5 5 5 5 5 ...... حتى حجم مجموعة كاملة

وأنا أعلم أن Tarski المستخدم الإجابة على هذا السؤال بطريقة مماثلة، ولكن أضفت بعض التفاصيل. يغفر بعض من بلدي C لأنا صدئ قليلا في ذلك حيث أنني أكثر ميلا إلى الرغبة في استخدام C ++، ولكن هنا غني.


إذا كنت تعرف حجم المصفوفة في وقت مبكر ...

#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" );
}

وهناك بعض المحاذير أعلاه؛ واحد هو أن UINT myArray[size]; لم يتم تهيئة مباشرة على الإعلان، ولكن كتلة التعليمات البرمجية التالي للغاية أو استدعاء دالة يقوم تهيئة كل عنصر من مجموعة لنفس القيمة التي تريدها. التحذير الآخر، سيكون لديك لكتابة initializing function لكل type سوف تدعم وعملتم أيضا إلى تعديل الدالة printArray() لدعم تلك الأنواع.


ويمكنك أن تجرب هذا الرمز مع المطيع على الانترنت وجدت هنا .

لتأخر التهيئة (أي الطبقة عضوا منشئ التهيئة) النظر فيما يلي:

int a[4];

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

مرة في اليوم (و أنا لا أقول أنها فكرة جيدة) ، كنا مجموعة العنصر الأول ثم:

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

ولا حتى التأكد من انها تعمل أي أكثر (هذا يعتمد على تنفيذ memcpy) لكنه يعمل من قبل مرارا وتكرارا نسخ العنصر الأولي التالي - حتى يعمل صفائف من الهياكل.

وأنا لا أرى أي الشروط الواردة في السؤال، لذلك يجب أن يكون حل عام: تهيئة مجموعة ربما متعددة الأبعاد غير محددة بنيت من عناصر بنية غير محددة وربما مع قيمة عضوا الأولية:

#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);
}

والنتيجة:

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'

وتحرير: تغير start+element_size إلى (char*)start+element_size

وأنا أعلم أن السؤال الأصلي يذكر صراحة C ++ C ولا، ولكن إذا (مثلي) جاء الى هنا بحثا عن حل للصفائف C ++، وهنا خدعة متقنة:

إذا يدعم المترجم الخاص بك أضعاف تعبيرات ، يمكنك استخدام قالب السحر و std::index_sequence لتوليد قائمة مهيئ مع القيمة التي تريدها. ويمكنك حتى constexpr ذلك ويشعر وكأنه مدرب:

#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

ويمكنك إلقاء نظرة على في العمل (وفي Wandbox)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top