2016-08-03 5 views
-1

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

char *me[] = {0}; 
getHardwareEEprom(me); 
printf("**%s\n", me[0]); // null 

void EEprom::getHardwareEEprom(char *eeprom[]) 
{ 
    char *EEPROM[]={"A4", "B3", "C=AB", "if(C7)", "(C)", NULL}; 
    eeprom = EEPROM; // set the address for the data array 
} 
  1. me указатель, который указывает на какое-то место
  2. его в этой функции, где она получает адрес некоторого массива в памяти
  3. me держит теперь адрес для массива EEPROM
  4. печать первого слова на нем нет

Независимо от того, как Я читал, я просто не понимаю, что это такое.

+4

Пожалуйста, прочтите [просить] и удалить '*' из первой строки – xenteros

ответ

7

Здесь нет ничего особенного.

Вы меняете то, что назначается параметру функции eeprom, вот и все. И это присвоение действителен для срока службы EEPROM.

Но это изменение не отражается в вызывающем абоненте (C++ - это пароль по значению). Таким образом, me в вызывающем устройстве остается таким, каким он был.

Это было бы совсем другое дело, если бы параметр функции eeprom был принят ссылка.

+0

Спасибо. Как бы вы передали его по ссылке? – Curnelious

+2

Используйте одну из этих штук '&' в списке параметров функции. – Bathsheba

+3

Позаботьтесь, это назначение недействительно, даже если 'EEPROM' не был освобожден. Ваша глобальная копия 'eeprom' не получит новое значение адреса. – naccyde

2

char *EEPROM[]={"A4", "B3", "C=AB", "if(C7)", "(C)", NULL}; имеет автоматическое хранилище, выделяется стек.

Он живет до тех пор, пока функция getHardwareEEprom не закончится и не вернется к вызывающему абоненту.

Также char *eeprom[] имеет локальную область действия, поэтому модификация внутри функции не отражается на переданном указателе.

В конце концов, решение типа C может быть

#include<stdio.h> 

void getHardwareEEprom(char ***eeprom) 
{ 
    static char *EEPROM[]={"A4", "B3", "C=AB", "if(C7)", "(C)", NULL}; 
    *eeprom = EEPROM; // set the address for the data array 
} 

int main(void) 
{ 
    size_t i=0; 
    char **me = {0}; 
    getHardwareEEprom(&me); 
    while(me[i] != NULL) 
    { 
     printf("%s\n", me[i]); 

     i++; 
    } 
} 
+0

Спасибо. что дает понять. Так есть ли способ получить ту же функциональность? – Curnelious

+0

Ну, много. Наконец, это [tag: C++], поэтому вы можете «новые» члены переданного указателя или просто сделать массив 'EEPROM'' static' или 'global' – LPs

+0

Я не думаю, что это на самом деле UB. Повторите еще раз, и понизите мой ответ, если я ошибаюсь. – Bathsheba

2

Вы назначая локальную переменную, EEPROM, которая выходит из области видимости, когда функция возвращает, так что это не справедливо, когда вы звоните printf.

1

аргументы передаются по значению в С. Заявление

eeprom = EEPROM; 

не имеет никакого эффекта в вызывающей функции.

1

Во-первых, это не C, но C++ (C не имеет класса, проверьте EEprom::).

Кроме того, позаботьтесь о масштабах ваших переменных. Здесь определяется char *EEPROM[]={"A4", "B3", "C=AB", "if(C7)", "(C)", NULL};, и память выделяется внутри вашей функции, поэтому, когда функция вернется, память будет освобождена.

Другая проблема заключается в том, что вы не можете задать адрес своего параметра, не возвращая его: при использовании аргумента по ссылке ваша функция получает копию вашего указателя. Затем в вашем примере локальная копия вашей функции eeprom изменит свой адрес на адрес EEPROM.Но глобальный экземпляр (он используется для вызова функции) не принимает новый адрес, чтобы обойти это, ваша функция может вернуть правильный адрес:

char **foo(void) 
{ 
    char **EEPROM = NULL; 
    // Here you should allocate your memory with malloc and fill the array with your data 

    return EEPROM; 
} 

char **bar = foo(); 

Таким образом, вы решить свои 2 проблемы: вы не используйте указатель на освобожденную память, и вы получите действительный указатель на свои данные вне функции.

1

Когда вы звоните getHardwareEEprom(me);, вы передаете функцию me функции, и этот адрес указан в вашей функции eeprom.

Но как только вы делаете eeprom = EEPROM; в вашей функции, сейчас нет связи. И, eeprom указывает на другое место целиком, то есть указывает на адрес массива EEPROM. Таким образом, eeprom и me больше не имеют отношения.

Чтобы изменить содержание me как вы ожидаете, что вам нужно сделать:

eeprom[0] = "test"; // OR 
*eeprom = "test"; 
Смежные вопросы