Trong C, tất cả các đối số hàm được truyền theo giá trị; bất kỳ thay đổi nào đối với tham số chính thức của hàm không được phản ánh trong tham số thực tế.Ví dụ:
void foo(int bar)
{
bar = bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(x);
printf("x after foo = %d\n", x);
return 0;
}
Đầu ra của chương trình sẽ được
x before foo = 0
x after foo = 0
vì bar
nhận giá trị của x
(0), không phải là một tài liệu tham khảo để x
riêng của mình. Thay đổi bar
không có hiệu lực trên x
.
Trong C, khoảng cách này là phải vượt qua một con trỏ cho một biến:
void foo(int *bar)
{
*bar = *bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(&x);
printf("x after foo = %d\n", x);
return 0;
}
Bây giờ đầu ra của chương trình là
x before foo = 0
x after foo = 1
Lần này, tham số chính thức bar
không phải là int, mà là con trỏ đến int và nó nhận được địa chỉ của x
(do biểu thức &x
trong cuộc gọi đến foo
), không phải giá trị chứa trong x. Biểu thức *bar
có nghĩa là "nhận giá trị trong thanh địa chỉ điểm đến", vì vậy *bar = *bar + 1
tương ứng với x = x + 1
.
Vì scanf()
cần ghi vào đối số của nó, nó hy vọng các đối số đó sẽ được nhập dưới dạng con trỏ. Trình chỉ định chuyển đổi "% d" dự kiến đối số tương ứng là con trỏ tới int (int *
), trình biến đổi chuyển đổi "% u" dự kiến con trỏ tới int chưa được ký (unsigned *
), "% s" dự kiến con trỏ đến char (char *
) , "% f" dự kiến con trỏ sẽ nổi (float *
), v.v. Trong ví dụ của bạn, vì a
được nhập int
, bạn cần sử dụng biểu thức &a
để nhận con trỏ.
Lưu ý rằng nếu a
đã là một kiểu con trỏ, bạn sẽ không cần phải sử dụng các nhà điều hành &
trong cuộc gọi đến scanf()
:
int main(void)
{
int a, *pa; // declare pa as a pointer to int
...
pa = &a; // assign address of a to pa
scanf("%d", pa); // scanf() will write to a through pa
...
}
Cũng lưu ý rằng khi đi qua một mảng tới một hàm (chẳng hạn như khi bằng cách sử dụng trình chỉ số chuyển đổi "% s" để đọc chuỗi), bạn không cần sử dụng toán tử &
; các biểu thức mảng ngầm sẽ được chuyển đổi sang một loại con trỏ:
int main(void)
{
char name[20];
...
scanf("%19s", name); // name implicitly converted from "char [20]" to "char *"
...
}
Như một bên, 'main' trả về' int', không phải 'void'. –