2017-01-15 2 views
1

Я пытался передать массив символов «p» функции «func» и скопировал ее в другой аргумент «arg» внутри функции. Но массив не копируется, хотя я могу изменять содержимое «p» в «func» и проверять изменения в основной функции, «res» не копируется со значениями от 'р'. Он печатает пустой. Я не уверен, какую ошибку я делаю.C - Возвращаемый массив как аргумент функции

#include <stdio.h> 
#include <stdlib.h> 

void func(char *c, int size, char *res) 
{ 
     int i; 
     printf("Printing c in func...\n"); 
     for(i=0;i<size;i++) { 
       printf("%c",c[i]); 
     } 
     printf("\n"); 
     c[2] = 'j'; 
     res = c; 
} 

int main(void) 
{ 
     char c[5]={'h','e','l','l','o'}; 
     char *p,*arg; 
     int i, size = 5; 
     p=c; 
     arg = (char*)malloc(size); 
     func(p,size,arg); 
     printf("Printing p in main...\n"); 
     for(i=0;i<size;i++) { 
       printf("%c",p[i]); 
     } 
     printf("\n"); 
     printf("Printing arg in main...\n"); 
     for(i=0;i<size;i++) { 
       printf("%c",arg[i]); 
     } 
     printf("\n"); 

     return 0; 
} 

Выход:

Printing c in func... 
hello 
Printing p in main... 
hejlo 
Printing arg in main... 

ответ

2

В C, аргументы функции передаются по значению. Расположение res и c не существует после завершения выполнения функции. Обратите внимание, что изменения, которые вы делаете, - это сами указатели, а не указатель местоположения. Поэтому любые изменения в res не будут видны main.

Для того, чтобы изменения были видимыми до main, вам необходимо пройти адрес arg, чтобы он работал func.

func подпись должна быть

void func(char *c, int size, char **res) ; 

и его вызов из main должен быть

func(p, size, &arg); 

изменить также назначение res = c; к *res = c; в функции func.

В этом случае вы передаете адрес указателя arg и изменения внесены в положение res указывает на. res указывает на адрес reg, поэтому любые изменения в адресе, указанном res, будут сохраняться и видны main.

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

 +-----------+    (0x300 is a random memory location) 
     |   | 
arg | 0x300 | <---------+ 
     |   |   | 
     +-----------+   | 
     0x100     | 
           | 
           | 
     +-----------+   | 
     |   |   | 
res | 0x100 +-----------+ 
     |   | 
     +-----------+ 
     0x200 

При назначении c на *res (псевдоним из reg), *res сделает reg, чтобы указать, где c указывает. Предполагая, что строка hello хранится в 0x500 тогда *res = c сделает reg, чтобы указать на 0x500:

              Array c (in main) 
     +-----------+         +-----+-----+-----+-----+-----+------+ 
     |   +--------------------------------->+ 'h' | 'e' | 'j' | 'l' | 'o' | '\0' | 
arg | 0x500 | <---------+      +-----+-----+-----+-----+-----+-------          
     |   |   |      0x500 .... 
     +-----------+   | 
     0x100     | 
           | *res = c 
           | 
     +-----------+   | 
     |   |   | 
res | 0x100 +-----------+ 
     |   | 
     +-----------+ 
     0x200 
+0

Спасибо. Затем, как изменения в массиве «p» остаются даже после выхода функции? – Gomu

+0

@Gomu; Отредактировал ответ. – haccks

1

В указатели C ар epassed по значению функции, поэтому в функции:

void func(char *c, int size, char *res) 

Рез является полностью другой объект, кроме указателя, переданного ему

func(p, size, arg); 

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

Поэтому назначение

res = c; 

с ума в том, что функция изменяет только локальный указатель (один внутри функции). Если вместо этого вы сделали

*res = *c; 

тогда память указал на будет изменен, и это будет видно снаружи функции, как память указывает на оригинальным указателем является же как один заостренный по res. Это также объясняет, почему написание 'j' в c[2] изменения исходного массива:

c[2] = 'j'; /* note: this is same as *(c + 2) = 'j'; and this is why it works - you 
       are using memory pointed to by pointer */ 

Если вам нужно изменить указатель сам нужно передать адрес для этого указателя вместо:

void func(char *c, int size, char **res) 
+0

Но как изменения в массиве «p» остаются даже после выхода функции? – Gomu

+0

Это потому, что c [2] = 'j' записывает 'j' в память, на которую указывает c + 2. – 4pie0

Смежные вопросы