Weisen Sie dem Array in C mehrere Werte zu

Lesezeit: 5 Minuten

Benutzeravatar von UnstableFractal
InstabilFraktal

Gibt es eine Möglichkeit, dies in komprimierter Form zu tun?

GLfloat coordinates[8];
...
coordinates[0] = 1.0f;
coordinates[1] = 0.0f;
coordinates[2] = 1.0f;
coordinates[3] = 1.0f;
coordinates[4] = 0.0f;
coordinates[5] = 1.0f;
coordinates[6] = 0.0f;
coordinates[7] = 0.0f;
return coordinates;

Etwas wie coordinates = {1.0f, ...};?

  • Geben Sie dort einen Zeiger auf eine lokale Variable zurück? Einige der Dinge, die Leute in den Antworten/Kommentaren unten gesagt haben, gehen entweder davon aus, dass die beteiligten Variablen automatisch sind oder dass sie es nicht sind. Könnte helfen, wenn Sie angeben.

    – Steve Jessop

    20. August 2010 um 23:45 Uhr


  • Sobald die Struktur initialisiert ist, gibt es keine einfache Möglichkeit, Mitglieder massenhaft zuzuweisen (außer dem Erstellen einer Kopie einer anderen Struktur mit memcpy). Ich wünsche mir oft, ich hätte diese Funktion.

    – bta

    21. August 2010 um 0:20 Uhr

  • Ich denke, Ihre ursprüngliche Antwort ist die beste – sie ist intuitiv, wenn auch etwas ausführlich, aber das ist für moderne Compiler kein Problem.

    – Yan König Yin

    29. Oktober 2015 um 4:28 Uhr

Benutzeravatar von James Curran
James Curran

Wenn du wirklich willst zuordnen Werte (im Gegensatz zu initialisieren), kannst du es so machen:

 GLfloat coordinates[8]; 
 static const GLfloat coordinates_defaults[8] = {1.0f, 0.0f, 1.0f ....};
 ... 
 memcpy(coordinates, coordinates_defaults, sizeof(coordinates_defaults));

 return coordinates; 

  • Besser noch, machen Sie es zu einer “statischen Konstante”, und Compiler können die Variable direkt aus dem Code heraus optimieren.

    – Zan Luchs

    20. August 2010 um 23:03 Uhr

  • @Zan Lynx: Werden die meisten Compiler nicht sowieso schlau genug sein, um das zu tun? Nun ja. Gute Praxis, um explizit zu sein, nehme ich an.

    – Chris Cooper

    20. August 2010 um 23:42 Uhr

  • @Chris Cooper: nicht, wenn es sich um eine globale handelt (die möglicherweise im Code geändert wird, den der Compiler nicht sehen kann). Sie können diesen Codeschnipseln nicht wirklich entnehmen, ob das “…” den Beginn einer Funktion ausschließt.

    – Steve Jessop

    20. August 2010 um 23:49 Uhr


  • @Steve: Guter Anruf. Danke fürs klarstellen.

    – Chris Cooper

    21. August 2010 um 0:06 Uhr

Benutzeravatar von Domen
dom

Obwohl in Ihrem Fall eine einfache Initialisierung ausreicht, gibt es einen Trick, um das Array in eine Struktur zu packen (die nach der Deklaration initialisiert werden kann).

Zum Beispiel:

struct foo {
  GLfloat arr[10];
};
...
struct foo foo;
foo = (struct foo) { .arr = {1.0, ... } };

Der Old-School-Weg:

GLfloat coordinates[8];
...

GLfloat *p = coordinates;
*p++ = 1.0f; *p++ = 0.0f; *p++ = 1.0f; *p++ = 1.0f;
*p++ = 0.0f; *p++ = 1.0f; *p++ = 0.0f; *p++ = 0.0f;

return coordinates;

  • Elegant, das gebe ich Ihnen zu, aber die Verwaltung eines vernünftigen Satzes von Initialisierungsdaten (mit eventueller Notwendigkeit, sie anzupassen) wird umständlich sein. Ich würde eine Syntax bevorzugen, bei der nur Daten (und möglicherweise einige Trennzeichen für Sichtbarkeitszwecke) ausreichen würden. Außerdem ist es Zeigerarithmetik. MISRA würde verrückt danach werden.

    – OpalApps

    4. April 2019 um 13:53 Uhr

Sie können Folgendes verwenden:

GLfloat coordinates[8] = {1.0f, ..., 0.0f};

Dies ist jedoch eine Initialisierung zur Kompilierzeit – Sie können diese Methode im aktuellen Standard nicht zum erneuten Initialisieren verwenden (obwohl ich denke, dass es im kommenden Standard Möglichkeiten gibt, dies zu tun, was Ihnen möglicherweise nicht sofort hilft).

Die anderen beiden Möglichkeiten, die mir in den Sinn kommen, sind, den Inhalt zu verleumden, wenn er behoben ist:

GLfloat base_coordinates[8] = {1.0f, ..., 0.0f};
GLfloat coordinates[8];
:
memcpy (coordinates, base_coordinates, sizeof (coordinates));

oder stellen Sie eine Funktion bereit, die trotzdem wie Ihr Initialisierungscode aussieht:

void setCoords (float *p0, float p1, ..., float p8) {
    p0[0] = p1; p0[1] = p2; p0[2] = p3; p0[3] = p4;
    p0[4] = p5; p0[5] = p6; p0[6] = p7; p0[7] = p8;
}
:
setCoords (coordinates, 1.0f, ..., 0.0f);

Denken Sie an diese Ellipsen (...) sind Platzhalter, keine Dinge, die buchstäblich in den Code eingefügt werden können.

Genau, fast hättest du es verstanden:

GLfloat coordinates[8] = {1.0f, ..., 0.0f};

  • @smsteel Diese Syntax gilt nur für Deklarationen

    – Michael Mrozek

    20. August 2010 um 22:58 Uhr

  • Das ist schlecht. Gibt es eine andere Möglichkeit, es zu vereinfachen? 🙂

    – Instabiles Fraktal

    20. August 2010 um 22:58 Uhr

Ich ging mit einer Array-Initialisierungsmethode:

#include <stdarg.h>

void int_array_init(int *a, const int ct, ...) {
  va_list args;
  va_start(args, ct);
  for(int i = 0; i < ct; ++i) {
    a[i] = va_arg(args, int);
  }
  va_end(args);
}

genannt wie,

const int node_ct = 8;
int expected[node_ct];
int_array_init(expected, node_ct, 1, 3, 4, 2, 5, 6, 7, 8);

Die C99-Array-Initialisierung wie folgt:

const int node_ct = 8;
const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };

Und in der configure.ac:

AC_PROG_CC_C99

hatte den Compiler auf meiner Dev-Box vollkommen zufrieden. Der Compiler auf dem Server beschwerte sich mit:

error: variable-sized object may not be initialized
   const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };

und

warning: excess elements in array initializer
   const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };

für jedes Element

Es beschwert sich zum Beispiel überhaupt nicht über:

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

Ich mag die Überprüfung der Größe und dass die varargs-Unterstützung robuster agiert als die Unterstützung für den Array-Initialisierer.

PR mit Beispielcode finden Sie unter https://github.com/wbreeze/davenport/pull/15/files

In Bezug auf https://stackoverflow.com/a/3535455/608359 von @paxdiablo hat es mir gefallen; fühlte mich jedoch unsicher, ob die Anzahl der Vorsprünge des Initialisierungszeigers mit der Anzahl der dem Array zugewiesenen Elemente synchronisiert werden sollte. Im schlimmsten Fall bewegt sich der Initialisierungszeiger über die zugewiesene Länge hinaus. Als solches enthält der Unterschied in der PR Folgendes:

  int expected[node_ct];
- int *p = expected;
- *p++ = 1; *p++ = 2; *p++ = 3; *p++ = 4;
+ int_array_init(expected, node_ct, 1, 2, 3, 4);

Das int_array_init -Methode weist Junk sicher zu, wenn die Anzahl der Argumente kleiner als node_ct ist. Die Junk-Zuweisung sollte einfacher zu erfassen und zu debuggen sein.

  • @smsteel Diese Syntax gilt nur für Deklarationen

    – Michael Mrozek

    20. August 2010 um 22:58 Uhr

  • Das ist schlecht. Gibt es eine andere Möglichkeit, es zu vereinfachen? 🙂

    – Instabiles Fraktal

    20. August 2010 um 22:58 Uhr

Benutzeravatar von dpi
dpi

Wenn Sie dieselben Aufgaben häufig in Ihrem Programm ausführen und eine Verknüpfung wünschen, besteht die einfachste Lösung möglicherweise darin, einfach eine Funktion hinzuzufügen

static inline void set_coordinates(
        GLfloat coordinates[static 8],
        GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3,
        GLfloat c4, GLfloat c5, GLfloat c6, GLfloat c7)
{
    coordinates[0] = c0;
    coordinates[1] = c1;
    coordinates[2] = c2;
    coordinates[3] = c3;
    coordinates[4] = c4;
    coordinates[5] = c5;
    coordinates[6] = c6;
    coordinates[7] = c7;
}

und dann einfach anrufen

GLfloat coordinates[8];
// ...
set_coordinates(coordinates, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f);

1405310cookie-checkWeisen Sie dem Array in C mehrere Werte zu

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy