ОБЪЯСНЕНИЕ
Это потому, что в C объявление массива внутри указателя затухает (см. Цитату в конце для деталей). Когда вы объявляете char a[]
, это аналогично объявлению char* a
. В обоих этих случаях a
хранит адрес памяти первого элемента массива. Но в случае таких переменных, как простые целые числа или символы, такие как int x = 10;
, переменная x
будет фактически хранить значение 10
.
Когда вы объявляете массив, такой как
char a[10];
объект, обозначенный выражением a
, представляет собой массив (т. Е. Непрерывный блок памяти, достаточно большой, чтобы вместить 10 символьных значений, или string ), и тип выражения a
- это «массив из 10 символьных элементов», или char[10]
. Выражение a
неявно преобразуется в char *
, и его значением является адрес первого элемента.
Таким образом, когда вы передаете переменную массива в функцию, вы фактически передаете адрес памяти ( или базовый адрес) массива. И так как вы написали объявление своей функции как:
void split(char take1[],char take2[], char str[])
Это то же самое, что и запись:
void split(char *take1,char *take2, char *str)
И, в вашем вызове функции, который:
split(taker1,taker2,str);
taker1
, taker2
и str
фактически содержат базовые адреса соответствующих символьных массивов (т. Е. Строки). Таким образом, вам не нужно явно упоминать оператор address_of (&
) вместе с переменными массива в вызове функции.
Отправленный вами код также может быть записан следующим образом :
void split(char *take1,char *take2, char *str){
int i=0,j=0,yes=0;
while(*(str+i) != '\0'){
if(*(str+i) == '*'){
yes=1;
i++;
}
if(yes==0){
*(take1+i) = *(str+i);
}
else if (yes!=0){
*(take2+i) = *(str+i);
j++;
}
i++;
}
}
int main(){
char taker1[30], taker2[30];
char str[30] = "Hello*world";
split(taker1, taker2, str);
printf("%s\n%s\n", taker1, taker2) ;
return 0;
}
Обратите внимание на оператор взаимозаменяемого массива ([]
) и оператор разыменования (*
). Подсказка: Запись arr[5]
совпадает с *(arr + 5)
.
КОРОТКО ДОЛГОЙ ИСТОРИИ:
- В C массивы передаются по ссылке. Нормальные переменные передаются по значению.
- Переменные массива можно рассматривать как указатели.
- Обычно при вызове функций следует пропустить
&
с переменными массива.
БОНУС
Вышеупомянутая причина также заключается в том, что мы не используем &
в scanf()
для строковых переменных (с %s
спецификатор формата), т. Е.
char str[10];
scanf("%s", str);
Но в случае целых чисел или других основных чисел:
int num;
scanf("%d", &num);
Кроме того, вы получите лучшее понимание задействованных понятий после того, как Dynami c Распределение памяти в C.
CITATION
Вот точный язык из C стандарт (n1256):
6.3.2.1 L Значения, массивы и указатели функций ... 3 За исключением случаев, когда это операнд оператора sizeof или унарный оператор & или строка литерал, используемый для инициализации массива, выражение с типом «массив типа» преобразуется в e xpression с типом '' указатель на тип '', который указывает на начальный элемент объекта массива и не является lvalue. Если объект массива имеет класс хранения регистров, поведение не определено.