30/09/2018, 17:11

`int (*a)[100]` khác với `int *a` và `int *a[100]` như thế nào?

Khi khai báo void Ham(int (*a)[100], int n, int m) thì a có ý nghĩa như thế nào?

  • int *aint(*a)[100]int *a[100] khác nhau như thế nào?
  • int (*a)[100] để làm gì?
Sáng Béo viết 19:28 ngày 30/09/2018

a là mảng 100 con trỏ.

Mai Anh Dũng viết 19:19 ngày 30/09/2018

a là mảng 100 con trỏ.

int *a[100] mới là mảng 100 con trỏ kiểu int

Chỗ này nó lằng nhằn một chỗ là có cái dấu (*a), nên ta phải đọc là

a là con trỏ, trỏ tới mảng 100 phần tử kiểu int


Tool giúp mình dịch khai báo C

http://cdecl.org/

Sáng Béo viết 19:18 ngày 30/09/2018

a xem lịch sử chỉnh sửa và thời gian chỉnh sửa cửa thớt đi ạ

Mai Anh Dũng viết 19:15 ngày 30/09/2018

Kakaka, hóa ra là vậy

Sorry @htwap nhé

Sáng Béo viết 19:18 ngày 30/09/2018

hí, không có gì đâu ạ.
mà không hiểu sao lại dùng cái (*a)[100] này nhỉ? vì theo a nói thì *a trỏ đến 1 mảng 100 phần tử, thế để mình *a mà không cần [100] có được ko a?

Mai Anh Dũng viết 19:25 ngày 30/09/2018

Khác nhau về khái niệm

  • Khai báo int (*a)[100] là cho biết a sẽ trỏ tới một mảng kiểu int, mảng này có 100 phần tử kiểu int.
  • Khai báo int *a là để cho biết a sẽ trỏ tới địa chỉ int, địa chỉ đó có thể là mảng.
  • Khai báo int *a[100] là cho biết a là mảng 100 phần tử, mỗi phần tử là một con trỏ kiểu int.

Khác nhau về kích thước giữa int *aint(*a)[100]

  • Khai báo int (*a)[100] là để khai báo rõ ràng rằng a trỏ tới mảng kiểu int với kích thước mỗi phần tử là 400 bytes bởi vì 100 * 4 bytes = 400 bytes. Cho int có kích thước 4 bytes.

  • Khai báo int *a thì a có thể trỏ tới mảng kiểu int với kích thước của mỗi phần tử là 4 bytes.

Ví dụ

#include <stdio.h>

int main() {
    int (*pa100)[100];
    int a100[100];
    pa100 = a100;
    printf("pa100 points to \t\t%p\n", *pa100);
    printf("a100 is on \t\t\t%p\n", a100);

    a100[1] = 3;

    printf("a100[1] = %d \t\t address %p\n", a100[1], &a100[1]);
    printf("pa100[1] = %d \t address %p\n", pa100[1], pa100[1]);

    return 0;
}

Kết quả

pa100 points to                 0028fd8c
a100 is on                      0028fd8c
a100[1] = 3              address 0028fd90
pa100[1] = 2686748       address 0028ff1c

Tại sao a100[1] bằng 3 trong khi pa100[1] = 2686748, trông có vẻ là số rác. Đó là bởi vì địa chỉ mà a100[1]pa100[1] trỏ đến là khác nhau.

Ta thấy:

  • 0028ff1c - 0028fd8c = 4, đúng bằng kích thước của một int
  • 0028ff1c - 0028fd8c = 400, đúng bằng kích thước của 100 int
huong viết 19:26 ngày 30/09/2018

Vậy có nghĩa theo anh Đạt khai báo:
int (*a)[100]; <=> int *a = new int[100]; phải không a.

Mai Anh Dũng viết 19:18 ngày 30/09/2018

Không phải @quanghuong1991 có thể in địa chỉ của hai khai báo này và địa chỉ sau khi tăng lên 1 để thấy có giống ví dụ của Đạt không.

Đạt không biết khai báo dùng new như thế nào để thể hiện được cái vụ thao tác + lên con trỏ mà tăng 400 địa chỉ. Nên Đạt làm tạm một ví dụ khác sử dụng một struct A100 có chứa int data[100]

#include <iostream>

struct A100{
    int data[100];
};

int main()
{
    int *pa = new int[100];
    std::cout << "address pa: " << pa << std::endl;
    std::cout << "address pa+1: " << pa+1 << std::endl;

    A100 *psa100 = new A100;
    std::cout << "address psa100: " << psa100 << std::endl;
    std::cout << "address psa100+1: " << psa100+1 << std::endl;
    return 0;
}

Output

address pa: 0x7f2580
address pa+1: 0x7f2584
address psa100: 0x7f2718
address psa100+1: 0x7f28a8

Ta chứng minh được là không phải

pa+1 - pa = 4 bytes

Còn về new một 100 phần tử kiểu int thì Đạt không biết phải new làm sao. Nên Đạt làm tạm cái struct A100.

Sáng Béo viết 19:24 ngày 30/09/2018

Ví dụ

ví dụ này thiếu *a[100] với *a nữa a ơi…

Mai Anh Dũng viết 19:27 ngày 30/09/2018

Cái này gọi là con trỏ mảng đúng không anh?

Rất có thể. Anh không biết thuật ngữ này, tại lúc anh đi học anh chưa học tới phần này.

ví dụ này thiếu *a[100] với *a nữa a ơi…

Ví dụ cho *a dễ mà. Ví dụ cho int *a[100] dở lắm. Anh thấy làm ví dụ cho char *bai_tho_con_coc[100] hay hơn. Em thử nghiên cứu char * s[100] rồi làm ví dụ xem. Đấy cũng là một cách học. Tự đặt câu hỏi: "char *schar *s[100] khác nhau như thế nào, khi nào dùng cái nào?"

huong viết 19:28 ngày 30/09/2018

E thấy theo định nghĩa thì khai báo:
int *pa = new int[100];(1)
là khai báo mảng gồm 100 phần tử kiểu int, giống với bên trên anh nói với khai báo int (*pa)[100];(2)
Hay nó khác nhau ở chỗ (1) la pa trỏ đến đầu mảng. Còn (2) trỏ đến nguyên cả mảng. Như vậy theo (2) thì e thấy không đúng lắm.

Mai Anh Dũng viết 19:18 ngày 30/09/2018

Em đọc định nghĩa bị nhầm rồi. new không phải là “khai báo mảng”, new là cấp phát vùng nhớ. Ở đây lệnh new chỉ cấp 400 bytes of RAM cho *pa thôi. Không liên quan gì khai báo kiểu dữ liệu *pa cả.

Về bản chất, *pa vẫn chỉ là int *pa, new không làm thay đổi nó. Anh có thể tách ra làm hai dòng lệnh khác nhau.

int *pa;
pa = new int[100];

Trong khi đó ta thấy khai báo này int (*pa)[100] hoàn toàn khác với khai báo int *pa. Đừng để ý tới vế sau dấu =. Để ý phần khai báo biến.

huong viết 19:16 ngày 30/09/2018

như vậy có phải
int (*pa)[100] chỉ là một con trỏ , và nó chỉ chứa địa chỉ của một mảng, mảng đó bắt buộc có 100 phần tử.
Vậy thì dùng cái này để làm gì ta. Dùng int *p vẫn linh động hơn nhiều .
ví dụ :
p thì có thể gán địa chỉ một biến int, một mảng một chiêu int bat kì só phần tử.
pa thì bi giới hạn rất nhiều

Mai Anh Dũng viết 19:17 ngày 30/09/2018

int (*pa)[100] chỉ là một con trỏ

Đúng

và nó chỉ chứa địa chỉ của một mảng, mảng đó bắt buộc có 100 phần tử.

Sai

int (*pa)[100] là một con trỏ, nó trỏ tới một vùng nhớ có độ dài 100 phần tử kiểu int.

Vậy thì dùng cái này để làm gì ta. Dùng int *p vẫn linh động hơn nhiều .

int *p là một con trỏ, trỏ tới một vùng nhớ có độ dài 1 phần tử kiểu int


Mảng, bản chất là một vùng nhớ liên tiếp. Ví dụ: int mang[100] là một vùng nhớ 400 bytes liên tiếp nhau. Nếu ta viết int *p = mang hoặc int *p = mang[0] tức là ta trỏ p tới vùng nhớ có độ dài 1 phần tử kiểu int.

Nếu ta viết p[1] hoặc (p+1), về bản chất ta trỏ tới phần tử kế tiếp của mang[0], phần tử này cũng là một vùng nhớ 4 bytes. Vùng nhớ này nằm trong int mang[100]

Nhưng nếu ta viết int (*p)[100] = mang hoặc int *p = mang[0] tức là ta trỏ tới vùng nhớ có độ dài 100 phần tử kiểu int. Lúc này p bao trùm toàn bộ mang[100], tức mang[1].

Nếu ta viết p[1] hoặc (p+1, về bản chất ta trỏ tới vùng nhớ cách xa vị trí mang[0] 400 bytes và nằm ngoài int mang[100].


Xem lại ví dụ ở trên: `int (*a)[100]` khác với `int *a` và `int *a[100]` như thế nào?

Hai công cụ khác nhau, dùng cho hai mục đích khác nhau.

lâm phúc tài viết 19:27 ngày 30/09/2018

anh Đạt ơi em chưa hiểu int a[100]; thì là 1 con trỏ hằng chỉ vào 1 mảng ô nhớ phía sau mà mỗi phần tử trong a[100] cũng coi như là 1 con trỏ, cho em hỏi nó khác gì với int*a[100] ạ

Mai Anh Dũng viết 19:22 ngày 30/09/2018

anh Đạt ơi em chưa hiểu int a[100]; thì là 1 con trỏ hằng

Đây không phải là con trỏ hằng, khi nào có const mới gọi là hằng. Đây gọi là mảng. Chỉ có điều mảng không gán được sang địa chỉ khác, nên người ta mới nói à, mảng giống như con trỏ hằng. Nhưng nó không phải. Mảng về bản chất nó không phải là con trỏ. Mảng là một địa chỉ.

em thử cái này xem

printf("%p %p\n", mang, &mang);
printf("%p %p\n", a, &a);

Nhưng cái này thuộc về câu hỏi khác rồi.

lâm phúc tài viết 19:23 ngày 30/09/2018

thank a, em sẽ coi lại ^^

abcxyz viết 19:20 ngày 30/09/2018

Mảng, bản chất là một vùng nhớ liên tiếp. Ví dụ: int mang[100] là một vùng nhớ 400 bytes liên tiếp nhau. Nếu ta viết int *p = mang hoặc int *p = mang[0] tức là ta trỏ p tới vùng nhớ có độ dài 1 phần tử kiểu int.

Nếu ta viết p[1] hoặc (p+1), về bản chất ta trỏ tới phần tử kế tiếp của mang[0], phần tử này cũng là một vùng nhớ 4 bytes. Vùng nhớ này nằm trong int mang[100]

Nhưng nếu ta viết int (*p)[100] = mang hoặc int *p = mang[0] tức là ta trỏ tới vùng nhớ có độ dài 100 phần tử kiểu int. Lúc này p bao trùm toàn bộ mang[100], tức mang[1].

Nếu ta viết p[1] hoặc (p+1, về bản chất ta trỏ tới vùng nhớ cách xa vị trí mang[0] 400 bytes và nằm ngoài int mang[100].

Anh xem e làm bảng này có đúng không ạ? e làm dựa vào những gì đọc được ở các bình luận trên
1.*pa

2.(*pa)[8]

3.*pa[8]

Mai Anh Dũng viết 19:20 ngày 30/09/2018

Cái 1 và 2 chính xác

cái 3 anh không hiểu lắm.

abcxyz viết 19:25 ngày 30/09/2018

cái 3 anh không hiểu lắm.

nghĩa là mảng con trỏ e viết tất cả các dấu * ở các phần tử ấy
pa[0] là con trỏ 1, vậy pa[0] + 5 ( cọng 1 số bất kì ) thì pa trỏ về đâu vậy anh?

Bài liên quan
0