2014-12-28 6 views
2

Я хотел бы научиться передавать по ссылке массив структур в second function, вызванный/выполненный из first function. Моя цель - изменить/изменить содержимое произвольной структуры из second functionтолько. Код ниже работает, но, к сожалению, не делает именно то, что я хочу достичь. Я хотел бы иметь доступ к произвольной структуре в пределах second function. Другими словами, я хотел бы обработать все структуры (используя цикл for) в пределах second function, позвонив/выполнив first function только в main только после и не используя for цикл.Передача массива структур в функцию?

second function, в нижеследующем коде, называется passByReference_inner.

array_of_struct.h:

struct card 
{ 
    int face; 
    int nose; 
}; 

typedef struct card HEAD ; 

/* prototype */ 
extern void passByReference(HEAD **c);  /* first function */ 
extern void passByReference_inner(HEAD *c); /* second function */ 

первая функция: (passByReference)

#include <stdio.h> 
#include "array_of_struct.h" 

void passByReference(HEAD **c) 
{ 
    passByReference_inner (*c); /* second function */ 
} 

Вторая функция: (passByReference_inner)

#include <stdio.h> 
#include "array_of_struct.h" 

void passByReference_inner(HEAD *c) 
{ 
    c->face = (c->face) + 1000; 
    c->nose = (c->nose) + 2000; 
} 

главная:

#include <stdio.h> 
#include "array_of_struct.h" 

int main(void) 
{ 
    int    i; 
    static HEAD  c[12]; 
    static HEAD *cptr[12]; 

    for (i = 0; i < 12; i++) 
    { 
     c[i].face = i + 30; 
     c[i].nose = i + 60; 
     cptr[i] = &c[i]; 
    } 

    for (i = 0; i < 12; i++) 
    { 
     passByReference(&cptr[i]); /* first function */ 
    } 
    return 0; 
} 
+0

Я хочу все вопросы были, как этот ... –

+0

язык C не может пройти по ссылке, только по значению; однако он может передать указатель. – user3629249

+0

в main() переменная 'cptr' и все использование могут быть полностью заменены ссылками на '& c [i]' – user3629249

ответ

1

Ваша вторая функция верна.

Указатель на первый элемент массива фактически совпадает с указателем на массив.

Что вы должны сделать, это

void passByReference_inner(HEAD *c, size_t n) 
{ 
} 

Таким образом, вы будете передавать указатель на первый элемент массива, а число элементов в массиве, что-то вроде этого:

passByReference(c, sizeof(c)/sizeof(c[0])); 

Это передаст указатель на первый элемент массива c и количество элементов в массиве - passByReference_inner(). sizeof (c) - размер всего массива в байтах. sizeof (c [0]) - размер элемента в массиве. Итак, если, например, каждая структура имеет длину 10 байтов (просто пример), и у вас есть массив из 12 структур, размер всего массива составляет 120 байтов, и это вычисляет значение 120/10 = 12, количество элементов в массиве, автоматически.

Когда вы используете имя объекта массива, в C/C++, который автоматически становится указателем на первый элемент массива.

В функции, вы можете работать с массивом следующим образом:

void passByReference_inner(HEAD *c, size_t n) 
{ 
    for (size_t i=0; i<n; i++) 
    { 
     HEAD *p=c+i; 

     // p is now a pointer to the ith element of the array 
    } 
} 

Добавление целое n указателю продвигает указатель на следующий nth элемент массива. Добавление целочисленного значения в указатель не продвигает указатель на это число байтов, а на количество байтов в объекте, на который указывает указатель, умноженный на число, которое вы добавляете (или вычитаете, то же самое). Это делает арифметику указателя правильной.

+0

«Когда вы используете имя объекта массива, в C/C++, который автоматически становится указателем« В C++, только в контексте, где ожидается указатель. Вы * можете * передавать указатели или ссылки на массивы заданного размера. (В C указатель на массив, похоже, привязан к любому старому указателю. Я не уверен, является ли это стандартным или расширением компилятора.) – juanchopanza

+0

@juanchopanza в этом вопросе нет C++. И что означает «что-то вроде привязки к любому старому указателю»? –

+0

@iharob Я имел в виду предложение в этом ответе, в котором упоминается «C/C++» (который может предполагать, что он применим к обоим языкам, поскольку нет гибридного языка C/C++). Что касается «... любого старого указателя», моя фразировка плоха, но, похоже, в C вы можете сказать «int (* p) [2] = & a;' где 'a' является' int'. В C++ 'a' должен быть' int [2] '. – juanchopanza

3

Я думаю, что вы пытаетесь сделать это

#include <stdio.h> 

struct card 
{ 
    int face; 
    int nose; 
}; 

typedef struct card HEAD ; 

/* prototype */ 
void passByReference(HEAD *c, int count);  /* first function */ 
void passByReference_inner(HEAD *c); /* second function */ 

void passByReference(HEAD *c, int count) 
{ 
    int i; 
    for (i = 0 ; i < count ; i++) 
     passByReference_inner (&(c[i])); /* second function */ 
} 

void passByReference_inner(HEAD *c) 
{ 
    c->face = (c->face) + 1000; 
    c->nose = (c->nose) + 2000; 
} 

int main(void) 
{ 
    int i; 
    HEAD c[12]; /* you don't need static here (do you know what static is for?) */ 

    for (i = 0; i < 12; i++) 
    { 
     c[i].face = i + 30; 
     c[i].nose = i + 60; 
    } 
    /* 
    * the element count of the array is sizeof(c)/sizeof(c[0]) 
    * (totalSizeOfArray)/(indivudualElementSizeOfArray). 
    */ 
    passByReference(c, sizeof(c)/sizeof(c[0])); /* first function */ 

    return 0; 
} 

, что вы должны знать, что массивы в c распаде на указатель, который указывает на их первого элемента, когда переданные как параметры для функций.

Так как вы хотите, чтобы обработать все в структурах второй функции, я не вижу необходимости в первой функции, в любом случае это, как вы могли бы сделать это тогда

#include <stdio.h> 

struct card 
{ 
    int face; 
    int nose; 
}; 

typedef struct card HEAD ; 

/* prototype */ 
void passByReference(HEAD *const c, int count);  /* first function */ 
void passByReference_inner(HEAD *const c, int count); /* second function */ 

void passByReference(HEAD *const c, int count) 
{ 
    passByReference_inner(c, count); /* second function */ 
} 

/* HEAD *const c prevents the pointer c to be changed 
* this way it will never point anywhere else. 
* 
* And you can be sure to alter the original data. 
*/ 
void passByReference_inner(HEAD *const c, int count) 
{ 
    for (int i = 0 ; i < count ; ++i) 
    { 
     c[i].face = (c[i].face) + 1000; 
     c[i].nose = (c[i].nose) + 2000; 
    } 
} 

int main(void) 
{ 
    int i; 
    HEAD c[12]; /* you don't need static here (do you know what static is for?) */ 

    for (i = 0; i < 12; i++) 
    { 
     c[i].face = i + 30; 
     c[i].nose = i + 60; 
    } 
    /* 
    * the element count of the array is sizeof(c)/sizeof(c[0]) 
    * (totalSizeOfArray)/(indivudualElementSizeOfArray). 
    */ 
    passByReference(c, sizeof(c)/sizeof(c[0])); /* first function */ 

    return 0; 
} 

, так как вы эффективно передавая указатель, вы меняете его содержимое непосредственно в обе функции первой и второй. более

Одна вещь, вы на самом деле не нужны static ключевое слово, особенно в main(), static сохраняет значение переменной между вызовами функции, а так как main() обычно вызывается только один раз в жизни программы .. . Нет смысла использовать static.

+0

Зачем вам делать 'HEAD'' static', если вы проходите мимо ссылки? –

+0

Я думаю, что OP хочет цикл 'for' внутри' passByReference_inner'. На самом деле не меняет сути ответа, но нуждается в небольшом перераспределении. – user3386109

+0

@ DavidC.Rankin Вы запутываете 'static' с' const'? – user3386109

0
  • Следующий код компилируется чистым способом.
  • Следующий код перемещает цикл значений инкремента
    внутри функции passByReference().

/* 
* Note: guard code is used in a header file 
*  so the header file can only be included once 
*  in each compilation unit 
*/ 

// note the inclusion of a 'guard' wrapper 
// begin: array_of_struct.h file 
#ifndef ARRAY_OF_STRUCT_H 
#define ARRAY_OF_STRUCT_H 

struct card 
{ 
    int face; 
    int nose; 
}; 

// dont obsecure the code with useless typedef statements 
//typedef struct card HEAD ; 

#define MAX_CARDS (12) 

/* prototype */ 
extern void passByReference(struct card *pCards);  /* first function */ 
extern void passByReference_inner(struct card *pCard); /* second function */ 
#endif 
// end: array_of_struct.h 


//first function: (passByReference), in different file 

#include <stdio.h> 
#include "array_of_struct.h" 

void passByReference(struct card *pCards) 
{ 
    int i=0; // loop index 

    for(i=0;i<MAX_CARDS;i++) 
    { 
     passByReference_inner (&pCards[i]); /* second function */ 
    } // end for 
} // end function: passByReference 

// second function: (passByReference_inner), in different file 

#include <stdio.h> 
#include "array_of_struct.h" 

void passByReference_inner(struct card *pCard) 
{ 
    pCard->face = (pCard->face) + 1000; 
    pCard->nose = (pCard->nose) + 2000; 
} // end function: passByReference_inner 

//main, in a different file 

#include <stdio.h> 
#include "array_of_struct.h" 

int main() 
{ 
    int i = 0; // loop index 
    static struct card  cards[MAX_CARDS]; 

    for (i = 0; i < MAX_CARDS; i++) 
    { 
     cards[i].face = i + 30; 
     cards[i].nose = i + 60; 
    } // end for 

    passByReference(&cards[0]); /* first function gets ptr to whole array*/ 
    // could also be written as: 
    // passByReference(cards); 

    return 0; 
} // end function: main 
0

Я проанализировал все три решения (iharob, user3629249, Сэм Varshavchik) и пришел к выводу, что Сэм Varshavchik и второе решение от iharob были правы на деньги. Первое решение iharob и решение user3629249, по сути, равны. Они переместили петлю for с main на first function. Второе решение сообщения iharob соответствует требованиям с начального поста. Решение Сэма дало мне достаточно подсказок/инструкций для «как переместить петлю for от основного до second function (что было, в основном, тем, что я не знал, как это сделать и поэтому просил о помощи).

Итак, чтобы сделать длинный рассказ коротким, вот исходный код, который реализует почти все предложения от всех участников. Код компилируется чистым образом, поэтому новички, подобные мне, могут принимать его как есть и узнать немного подробностей о указателе на указатель, арифметику указателей и массив массивов.

array_of_struct.h (заголовочный файл)

#ifndef ARRAY_OF_STRUCT_H 
#define ARRAY_OF_STRUCT_H 

/* HEAD structure definition */ 
typedef struct 
{ 
    int face; 
    int nose; 
} HEAD;  // end structure HEAD 

#define MAX_HEADS (12) 

/* prototype */ 
extern void passByReference(HEAD **c, size_t n); 
extern void passByReference_inner(HEAD *c, size_t n); 

#endif 

passByReference.c (первая функция)

#include <stdio.h> 
#include "array_of_struct.h" 

void passByReference(HEAD **c, size_t n) 
{ 
    passByReference_inner (*c, n); 
} 

passByReference_inner.с (вторая функция)

#include <stdio.h> 
#include "array_of_struct.h" 

void passByReference_inner(HEAD *c, size_t n) 
{ 
    int i; 
    HEAD *p; 

    printf("\nPOINTER ARITHMETIC: The value of struct's members after PASS BY REFERENCE \n"); 
    for (i = 0; i < n; i++) 
    { 
     p = c + i; 

     p->face = (p->face) + 1000; 
     p->nose = (p->nose) + 2000; 
     printf("struct[%i].face = %d \n",i, p[0].face); 
     printf("struct[%i].nose = %d \n",i, p[0].nose); 
    } 

    printf("\nARRAY INDEX MATH: The value of struct's members after PASS BY REFERENCE\n"); 
    printf("[NOTE: structs were updated in the for loop above]\n"); 
    for (i = 0; i < n; i++) 
    { 
     printf("struct[%i].face = %d \n",i, c[i].face); 
     printf("struct[%i].nose = %d \n",i, c[i].nose); 
    } 
} 

main.c

#include <stdio.h> 
#include "array_of_struct.h" 

int main(void) 
{ 
    int  i; 
    HEAD c[MAX_HEADS]; 
    HEAD *cptr; 
    size_t n; 

    n = (sizeof(c)/sizeof(c[0]); 

    printf("\nINITIALIZATION of all struct's members\n"); 
    for (i = 0; i < n; i++) 
    { 
     c[i].face = i + 30; 
     c[i].nose = i + 60; 
     printf("struct[%i].face = %d\n",i, c[i].face); 
     printf("struct[%i].nose = %d\n",i, c[i].nose); 
    } 

    cptr = &c[0]; 
    passByReference(&cptr, n); 

    return 0; 
} 
Смежные вопросы