Czy można podjąć adres obiektu po prawej stronie jego definicji, jak się dzieje w foo() poniżej:

typedef struct { char x[100]; } chars;

chars make(void *p) {
  printf("p = %p\n", p);
  chars c;
  return c;
}

void foo(void) {
  chars b = make(&b);
}

Jeśli jest dozwolone, czy istnieje jakieś ograniczenie w jego użyciu, np. Drukowanie go w porządku, czy mogę porównać go do innego wskaźnika itp.

W praktyce wydaje się kompilować na kompilatach, które przetestowałem, z oczekiwanym zachowaniem przez większość czasu (ale Nie zawsze), Ale to daleko od gwarancji.

3
BeeOnRope 3 czerwiec 2018, 09:37

2 odpowiedzi

Aby odpowiedzieć na pytanie w tytule, z myślą o próbce kodu, tak, tak może. Standard C mówi tyle samo w §6.2.4 :

Życie obiektu jest część wykonania programu, podczas której gwarantuje się przechowywanie do niego zarezerwowane. Obiekt istnieje, ma stały adres i zachowuje swoją ostatnią wartość przechowywaną przez całe życie.

Dla takiego obiektu, który nie ma typu tablicy o zmiennej długości, jego czas życia rozciąga się od wejścia do bloku, z którym jest związany, dopóki nie jest związany z wykonywaniem tego bloku w żaden sposób.

Więc tak, możesz podjąć adres zmiennej z punktu deklaracji, ponieważ obiekt ma adres w tym momencie i jest w zasięgu. Skrócony przykład tego jest:

void *p = &p;

Służy bardzo mało celów, ale jest całkowicie ważny.

Jeśli chodzi o twoje drugie pytanie, co możesz z tym zrobić. Mogę głównie powiedzieć, że nie użyję tego adresu, aby uzyskać dostęp do obiektu, dopóki inicjalizacja zostanie zakończona, ponieważ kolejność oceny wyrażeń w inicjalizacjach pozostaje niezapozowany ( §6.7.9 ). Możesz łatwo znaleźć stóp stóp.

Jedno miejsce, w którym to się dzieje, jest określenie wszelkiego rodzaju struktur danych tabelarycznych, które muszą być referencyjne. Na przykład:

typedef struct tab_row {
  // Useful data
  struct tab_row *p_next;
} row;

row table[3] = {
  [1] = { /*Data 1*/, &table[0] },
  [2] = { /*Data 2*/, &table[1] },
  [0] = { /*Data 0*/, &table[2] },
};
8
StoryTeller - Unslander Monica 3 czerwiec 2018, 07:15

Odpowiedzi na pytanie, ale w celach informacyjnych nie ma znaczenia. W ten sposób napisałbyś kod:

typedef struct { char x[100]; } chars;

chars make (void) {
  chars c;
  /* init c */
  return c;
}

void foo(void) {
  chars b = make();
}

A może korzystnie w przypadku ADT lub podobnego zwróć wskaźnik do obiektu malloc: ED. Przekazywanie strukturki według wartości zwykle nie jest dobrym pomysłem.

0
Lundin 4 czerwiec 2018, 06:50