Câu hỏi Tôi có cast kết quả của malloc không?


Trong câu hỏi này, ai đó đã đề xuất trong một bình luận mà tôi nên không phải đúc kết quả của malloc, I E.

int *sieve = malloc(sizeof(int) * length);

thay vì:

int *sieve = (int *) malloc(sizeof(int) * length);

Tại sao nó lại là vấn đề?


2043
2018-03-03 10:13


gốc


Ngoài ra, nó là duy trì hơn để viết sieve = malloc (sizeof * sàng * chiều dài); - William Pursell
stackoverflow.com/q/7545365/168175 - Flexo♦
@ KarolyHorvath đây không phải là lý do duy nhất. Khác (và quan trọng nhất, IMHO), là làm cho mã linh hoạt hơn (nhưng không kém an toàn hoặc mạnh mẽ) nếu loại sieve thay đổi từ int, nói, float. malloc( sizeof *sieve * length ); sẽ hoạt động bất kể loại nào, trong khi diễn viên cần bảo trì, không thêm gì và có thể tạo khó khăn để theo dõi lỗi. - MestreLion
@MestreLion: "và có thể tạo khó khăn để theo dõi lỗi" - tất cả những gì bạn phải làm là bật cảnh báo biên dịch và không bao giờ sắp xảy ra. OTOH nếu bạn không ... bạn thực sự xứng đáng với nó. và, một lần nữa, tôi không phải là người ủng hộ việc sử dụng nó .. tất cả tôi nói rằng nó thực sự không quan trọng ... đó là chủ yếu vô hại :) - Karoly Horvath
Xem thêm Cụ thể, điều gì nguy hiểm khi truyền kết quả của malloc()? - Jonathan Leffler


Các câu trả lời:


Không; bạn không đúc kết quả, vì:

  • Nó là không cần thiết, như void * được kích hoạt tự động và an toàn cho bất kỳ loại con trỏ nào khác trong trường hợp này.
  • Nó thêm lộn xộn vào mã, phôi không phải là rất dễ đọc (đặc biệt là nếu loại con trỏ dài).
  • Nó làm cho bạn lặp lại chính mình, mà nói chung là xấu.
  • Nó có thể ẩn một lỗi nếu bạn quên bao gồm <stdlib.h>. Điều này có thể gây ra sự cố (hoặc tệ hơn, không phải gây ra một vụ tai nạn cho đến khi sau này trong một số phần hoàn toàn khác nhau của mã). Xem xét điều gì sẽ xảy ra nếu con trỏ và số nguyên có kích thước khác nhau; sau đó bạn đang ẩn một cảnh báo bằng cách truyền và có thể mất các bit trong địa chỉ được trả lại của bạn. Lưu ý: khi các hàm ẩn của C11 biến mất khỏi C và điểm này không còn liên quan nữa vì không có giả định tự động nào mà hàm undeclared trả về int.

Khi làm rõ, lưu ý rằng tôi đã nói "bạn không bỏ", không phải "bạn không nhu cầu Theo ý kiến ​​của tôi, đó là một thất bại trong việc bao gồm dàn diễn viên, ngay cả khi bạn làm đúng, chỉ đơn giản là không có lợi ích để làm điều đó, nhưng một loạt các rủi ro tiềm ẩn, và bao gồm cả các diễn viên chỉ ra rằng bạn không biết về những rủi ro.

Cũng lưu ý, như các nhà bình luận chỉ ra, rằng các cuộc đàm phán ở trên về thẳng C, không phải C ++. Tôi rất tin tưởng vào C và C ++ là ngôn ngữ riêng biệt.

Để bổ sung thêm, mã của bạn không cần thiết lặp lại thông tin kiểu (int) có thể gây ra lỗi. Nó tốt hơn để dereference con trỏ được sử dụng để lưu trữ các giá trị trả về, để "khóa" hai với nhau:

int *sieve = malloc(length * sizeof *sieve);

Điều này cũng di chuyển length về phía trước để tăng khả năng hiển thị và giảm các dấu ngoặc đơn thừa với sizeof; họ chỉ cần khi đối số là tên loại. Nhiều người dường như không biết (hoặc bỏ qua) điều này, khiến mã của họ tiết lộ chi tiết hơn. Nhớ lại: sizeof không phải là một chức năng! :)


Trong khi di chuyển length phía trước có thể tăng khả năng hiển thị trong một số trường hợp hiếm hoi, người ta cũng nên chú ý rằng trong trường hợp chung, tốt hơn nên viết biểu thức là:

int *sieve = malloc(sizeof *sieve * length);

Kể từ khi giữ sizeof đầu tiên, trong trường hợp này, đảm bảo phép nhân được thực hiện với ít nhất size_t môn Toán.

So sánh: malloc(sizeof *sieve * length * width) so với malloc(length * width * sizeof *sieve) thứ hai có thể tràn length * width khi nào width và length là loại nhỏ hơn size_t.


1917
2018-03-03 10:17



@unwind Không, ngay cả trong mã C nghiêm ngặt, tôi sử dụng các diễn viên cho tính di động. Những gì tôi có nghĩa là bởi tính di động là di động cho các phiên bản cũ của tiêu chuẩn c nơi void * 's không được thăng chức. Tôi trích dẫn từ "Ngôn ngữ lập trình C" của K & R: "Trong C, phương pháp thích hợp là khai báo rằng malloc trả về một con trỏ để làm mất hiệu lực, sau đó ép buộc con trỏ vào kiểu mong muốn với một dàn diễn viên." Lý do mà tôi áp đặt một yêu cầu như vậy là bạn không luôn luôn có một sự lựa chọn của trình biên dịch bạn có thể sử dụng. - chacham15
@ chacham15 Trong khi có các phiên bản trước của C ngôn ngữ nơi diễn viên là cần thiết (K & R C không có void* loại!), các phiên bản đó chưa bao giờ Tiêu chuẩn. C89 (phiên bản tiêu chuẩn hóa đầu tiên) yêu cầu malloc trở về void* và đó void* được chuyển đổi hoàn toàn. - jamesdlin
@Soumen Nó có lẽ quá tối nghĩa; không bao gồm loại trả về int sẽ được giả định, có thể nhỏ hơn void *, do đó, nhiệm vụ có thể tạo ra một cảnh báo, mà sẽ bị đàn áp bởi các diễn viên. Xem câu hỏi nàyví dụ. - unwind
@unwind Hầu hết các trình biên dịch sẽ cảnh báo bạn về một hàm được xác định ngầm ... (vì vậy tôi không thấy sự nguy hiểm của diễn viên) - DarthRubik
@ n.m. Được. Tôi nghĩ rằng thật tệ khi cho rằng bất cứ ai đọc ở đây đều có một trình biên dịch cụ thể. Ngoài ra, vì C11 toàn bộ khái niệm "hàm ẩn" đã biến mất, tôi không biết điều đó. Tuy nhiên, tôi không thấy điểm trong việc thêm một diễn viên vô nghĩa. Bạn cũng làm int x = (int) 12; chỉ để làm mọi thứ rõ ràng? - unwind


Trong C, bạn không cần truyền giá trị trả về của malloc. Con trỏ để void được trả về bởi malloc được tự động chuyển đổi thành loại chính xác. Tuy nhiên, nếu bạn muốn mã của bạn để biên dịch với một trình biên dịch C ++, một diễn viên là cần thiết. Một lựa chọn ưu tiên trong cộng đồng là sử dụng những điều sau đây:

int *sieve = malloc(sizeof *sieve * length);

giúp bạn không phải lo lắng về việc thay đổi phía bên phải của biểu thức nếu bạn thay đổi loại sieve.

Casts là xấu, như mọi người đã chỉ ra. Con trỏ đặc biệt phôi.


327
2018-03-03 10:17



@MAKZ Tôi cho rằng malloc(length * sizeof *sieve) làm cho nó trông giống như sizeof là một biến - vì vậy tôi nghĩ malloc(length * sizeof(*sieve)) dễ đọc hơn. - Michael Anderson
Và malloc(length * (sizeof *sieve)) vẫn dễ đọc hơn. IMHO. - Toby Speight
@Michael Anderson () phát hành sang một bên, lưu ý rằng phong cách được đề xuất của bạn đã thay đổi thứ tự., Hãy cân nhắc khi tính phần tử được tính như length*width, giữ sizeof đầu tiên trong trường hợp này đảm bảo phép nhân được thực hiện với ít nhất size_t môn Toán. So sánh malloc(sizeof( *ptr) * length * width) so với malloc(length * width * sizeof (*ptr)) - thứ 2 có thể tràn length*width khi nào width,length là loại nhỏ hơn size_t. - chux
@chux không rõ ràng, nhưng câu trả lời đã được chỉnh sửa để nhận xét của tôi ít thích hợp hơn - đề xuất ban đầu là malloc(sizeof *sieve * length) - Michael Anderson
C không phải là C ++. Giả vờ rằng họ cuối cùng sẽ dẫn đến sự nhầm lẫn và buồn bã. Nếu bạn đang sử dụng C ++, sau đó một diễn viên kiểu C cũng là xấu (trừ khi bạn đang sử dụng một trình biên dịch C ++ rất cũ). Và static_cast>() (hoặc là reinterpret_cast<>() ) không tương thích với bất kỳ phương ngữ nào của C. - David C.


Bạn làm cast, bởi vì:

  • Nó làm cho mã của bạn di động nhiều hơn giữa C và C ++, và như kinh nghiệm SO cho thấy, rất nhiều lập trình viên tuyên bố họ đang viết bằng C khi họ đang thực sự viết bằng C ++ (hoặc C cộng với phần mở rộng trình biên dịch cục bộ).
  • Không làm như vậy có thể ẩn một lỗi: lưu ý tất cả các ví dụ về việc khó hiểu khi viết type * đấu với type **.
  • Ý tưởng rằng nó giúp bạn không nhận thấy bạn đã thất bại #include một tập tin tiêu đề thích hợp bỏ lỡ rừng cây. Nó cũng giống như nói "đừng lo lắng về thực tế bạn không yêu cầu trình biên dịch phàn nàn về việc không nhìn thấy nguyên mẫu - rằng stdlib.h pesky là điều quan trọng REAL cần nhớ!"
  • Nó ép buộc kiểm tra chéo nhận thức bổ sung. Nó đặt loại (mong muốn) mong muốn ngay bên cạnh số học bạn đang làm cho kích thước thô của biến đó. Tôi đặt cược bạn có thể làm một nghiên cứu SO cho thấy rằng malloc() lỗi được phát hiện nhanh hơn nhiều khi có dàn diễn viên. Cũng giống như với các xác nhận, chú thích tiết lộ ý định giảm lỗi.
  • Lặp lại bản thân theo cách mà máy có thể kiểm tra thường là tuyệt quá ý kiến. Trong thực tế, đó là những gì một khẳng định là, và sử dụng này của diễn viên là một khẳng định. Các xác nhận vẫn là kỹ thuật chung nhất mà chúng tôi có để nhận mã đúng, vì Turing đã đưa ra ý tưởng rất nhiều năm trước.

292
2018-02-14 16:15



Trong trường hợp bạn không biết, bạn có thể viết mã biên dịch cả C và C ++. Trong thực tế, hầu hết các tập tin tiêu đề là như thế này, và chúng thường chứa mã (macro và hàm nội tuyến). Có một .c/.cpp tập tin để biên dịch như cả hai không hữu ích rất thường xuyên, nhưng một trường hợp là thêm C ++ throw hỗ trợ khi biên dịch với trình biên dịch C ++ (nhưng return -1; khi biên dịch với trình biên dịch C, hoặc bất kỳ thứ gì). - hyde
Nếu ai đó có lệnh gọi nội tuyến trong một tiêu đề tôi sẽ không bị ấn tượng, #ifdef __cplusplus và extern "C" {} là dành cho công việc này, không thêm vào các phôi phụ. - paulm
Vâng, điểm 1 là không liên quan, vì C! = C ++, các điểm khác cũng tầm thường, nếu bạn sử dụng biến trong của bạn malloc gọi điện: char **foo = malloc(3*sizeof(*foo)); nếu khá đầy đủ bằng chứng: 3 con trỏ đến con trỏ char. sau đó lặp lại và thực hiện foo[i] = calloc(101, sizeof(*(foo[i])));. Phân bổ mảng 101 ký tự, được khởi tạo gọn gàng thành số không. Không cần diễn viên. thay đổi tuyên bố thành unsigned char hoặc bất kỳ loại nào khác, cho vấn đề đó, và bạn vẫn tốt - Elias Van Ootegem
Khi tôi nghĩ tôi đã nhận được nó, nó đến! Câu trả lời tuyệt vời. Đây là lần đầu tiên ở đây trong StackOverflow mà tôi +1 hai câu trả lời ngược lại! +1 Không, bạn không truyền, và +1 Có, bạn đã bỏ! LOL. Các bạn thật tuyệt vời. Và đối với tôi và học sinh của tôi, tôi đã quyết định: Tôi sẽ tham gia. Loại lỗi mà sinh viên mắc phải dễ phát hiện hơn khi truyền. - Dr Beco
@Leushenko: Lặp lại bản thân theo cách không thể được xác nhận bằng máy hoặc kiểm tra địa phương là không tốt. Lặp lại chính mình theo những cách có thể được xác nhận bằng các phương tiện như vậy là ít xấu. Được struct Zebra *p; ... p=malloc(sizeof struct Zebra);, malloc không thể tránh thông tin duplciating về loại p, nhưng không phải trình biên dịch cũng như kiểm tra mã địa phương sẽ phát hiện bất kỳ vấn đề nếu một loại thay đổi nhưng khác không. Thay đổi mã thành p=(struct Zebra*)malloc(sizeof struct Zebra);và trình biên dịch sẽ làm mờ nếu kiểu truyền không khớp pvà địa phương kiểm tra sẽ tiết lộ ... - supercat


Như đã nói khác, nó không cần thiết cho C, nhưng đối với C ++. Nếu bạn nghĩ rằng bạn sẽ biên dịch mã C của bạn bằng trình biên dịch C ++, vì lý do nào đó, bạn có thể sử dụng macro thay vì, như:

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif

Bằng cách đó bạn vẫn có thể viết nó theo một cách rất nhỏ gọn:

int *sieve = NEW(int, 1);

và nó sẽ biên dịch cho C và C ++.


148
2018-03-03 11:17



Vì bạn đang sử dụng macro, tại sao bạn không sử dụng macro new trong định nghĩa của C ++? - Hosam Aly
Bởi vì không có lý do để làm như vậy. Nó chủ yếu cho các chương trình C được biên dịch bằng trình biên dịch C ++. Nếu bạn sẽ sử dụng 'mới', điều duy nhất bạn nhận được là vấn đề. Bạn cũng cần một macro miễn phí. Và bạn cần một macro để giải phóng một mảng, một sự khác biệt không tồn tại trong C. - quinmars
Không phải đề cập đến nếu nó không phải là bạn giải phóng bộ nhớ nhưng có thể là một thư viện C bạn đang sử dụng, vv Nhiều vấn đề có thể mà không có bất kỳ lợi ích nào. - quinmars
@ Hosam: Vâng, chắc chắn là vậy. Nếu bạn dùng new bạn phải dùng delete và nếu bạn sử dụng malloc() bạn phải là bạn free(). Không bao giờ trộn chúng. - Graeme Perrow
Nếu một người sẽ thực hiện phương pháp này, hãy gọi macro NEW có lẽ là một ý tưởng tồi vì tài nguyên không bao giờ được trả lại bằng delete (hoặc là DELETE) vì vậy bạn đang trộn từ vựng của bạn. Thay vào đó, đặt tên cho nó MALLOC, hay đúng hơn CALLOC trong trường hợp này, sẽ có ý nghĩa hơn. - mah


Từ Wikipedia

Ưu điểm để đúc

  • Bao gồm các diễn viên có thể cho phép một chương trình C hoặc chức năng để biên dịch như C + +.

  • Dàn diễn viên cho phép các phiên bản trước năm 1989 của malloc ban đầu trả về một char *.

  • Việc đúc có thể giúp nhà phát triển xác định sự mâu thuẫn trong việc định kích thước kiểu con trỏ đích, đặc biệt nếu con trỏ được khai báo xa cuộc gọi malloc () (mặc dù trình biên dịch hiện đại và phân tích tĩnh có thể cảnh báo về hành vi đó mà không yêu cầu diễn viên).

Nhược điểm để đúc

  • Theo tiêu chuẩn ANSI C, dàn diễn viên thừa.

  • Việc thêm diễn viên có thể che giấu không bao gồm tiêu đề stdlib.h, trong   mà nguyên mẫu cho malloc được tìm thấy. Trong trường hợp không có   nguyên mẫu cho malloc, tiêu chuẩn yêu cầu trình biên dịch C   giả sử malloc trả về một int. Nếu không có diễn viên, cảnh báo là   được cấp khi số nguyên này được gán cho con trỏ; tuy nhiên, với   các diễn viên, cảnh báo này không được sản xuất, ẩn một lỗi. Trên một số   kiến trúc và mô hình dữ liệu (chẳng hạn như LP64 trên các hệ thống 64 bit, trong đó   dài và con trỏ là 64-bit và int là 32-bit), lỗi này có thể   thực sự dẫn đến hành vi không xác định, như được khai báo ngầm   malloc trả về một giá trị 32 bit trong khi hàm thực sự được định nghĩa   trả về giá trị 64 bit. Tùy thuộc vào quy ước và bộ nhớ gọi   bố trí, điều này có thể dẫn đến ngăn xếp đập. Vấn đề này ít có khả năng   để không được chú ý trong các trình biên dịch hiện đại, khi chúng sản xuất đồng đều   cảnh báo rằng một chức năng không khai báo đã được sử dụng, vì vậy một cảnh báo sẽ   vẫn xuất hiện. Ví dụ, hành vi mặc định của GCC là hiển thị   cảnh báo đọc "tuyên bố ngầm không tương thích được tích hợp sẵn   chức năng "không phụ thuộc vào việc dàn diễn viên có hiện diện hay không.

  • Nếu loại con trỏ được thay đổi khi khai báo, có thể   Ngoài ra, cần phải thay đổi tất cả các dòng mà malloc được gọi và cast.

Mặc dầu malloc mà không cần đúc là phương pháp ưa thích và hầu hết các lập trình viên có kinh nghiệm chọn nó, bạn nên sử dụng bất cứ điều gì bạn thích có nhận thức được các vấn đề.

tức là: Nếu bạn cần biên dịch chương trình C thành C ++ (Mặc dù đó là ngôn ngữ riêng biệt), bạn nên sử dụng malloc với đúc.


96
2017-10-09 21:23



Những gì "Việc đúc có thể giúp nhà phát triển xác định sự mâu thuẫn trong việc định kích thước kiểu nếu kiểu con trỏ đích thay đổi, đặc biệt nếu con trỏ được khai báo cách xa malloc() gọi điệnBạn có thể đưa ra một ví dụ? - Cool Guy
@CoolGuy: Xem nhận xét trước đó về câu trả lời khác. Nhưng lưu ý rằng p = malloc(sizeof(*p) * count) thành ngữ tự động chọn các thay đổi trong loại, do đó bạn không phải nhận cảnh báo và thay đổi bất kỳ thứ gì. Vì vậy, đây không phải là một lợi thế thực sự so với thay thế tốt nhất cho không đúc. - Peter Cordes
Đây là câu trả lời thích hợp: Có những ưu và khuyết điểm, và nó sôi xuống đến một vấn đề của hương vị (trừ khi mã phải biên dịch như C ++ - sau đó diễn viên là bắt buộc). - Peter A. Schneider
Điểm 3 là tranh luận, vì nếu kiểu của con trỏ được thay đổi tại khai báo của nó, người ta nên kiểm tra tất cả các thể hiện của malloc, realloc và tự do giải quyết loại đó. Việc đúc sẽ buộc bạn phải làm điều đó. - Michaël Roy


Trong C, bạn có thể chuyển đổi hoàn toàn một con trỏ void thành bất kỳ loại con trỏ nào khác, do đó, một diễn viên là không cần thiết. Sử dụng một người có thể gợi ý cho người quan sát bình thường rằng có một số lý do tại sao người ta cần thiết, điều này có thể gây hiểu nhầm.


94
2018-03-03 10:18





Bạn không cast kết quả của malloc, bởi vì làm như vậy thêm vô nghĩa lộn xộn vào mã của bạn.

Lý do phổ biến nhất tại sao mọi người bỏ kết quả của malloc là vì họ không chắc chắn về cách ngôn ngữ C hoạt động. Đó là một dấu hiệu cảnh báo: nếu bạn không biết cơ chế ngôn ngữ cụ thể hoạt động như thế nào, thì không hãy đoán. Tra cứu hoặc hỏi về Stack Overflow.

Một vài bình luận:

  • Một con trỏ void có thể được chuyển đổi thành / từ bất kỳ loại con trỏ nào khác mà không có một diễn viên rõ ràng (C11 6.3.2.3 và 6.5.16.1).

  • Tuy nhiên, C ++ sẽ không cho phép diễn xuất ngầm giữa void* và một loại con trỏ khác. Vì vậy, trong C ++, dàn diễn viên sẽ đúng. Nhưng nếu bạn lập trình bằng C ++, bạn nên sử dụng new và không phải malloc (). Và bạn không bao giờ nên biên dịch mã C bằng trình biên dịch C ++.

    Nếu bạn cần hỗ trợ cả C và C ++ với cùng một mã nguồn, hãy sử dụng các trình chuyển đổi trình biên dịch để đánh dấu sự khác biệt. Đừng cố gắng sate cả hai tiêu chuẩn ngôn ngữ với cùng một mã, bởi vì họ không tương thích.

  • Nếu một trình biên dịch C không thể tìm thấy một hàm bởi vì bạn quên bao gồm tiêu đề, bạn sẽ nhận được một lỗi trình biên dịch / liên kết về điều đó. Vì vậy, nếu bạn quên bao gồm <stdlib.h> đó không phải là vấn đề lớn, bạn sẽ không thể xây dựng chương trình của mình.

  • Trên các trình biên dịch cổ xưa theo một phiên bản tiêu chuẩn đã hơn 25 năm, quên bao gồm <stdlib.h> sẽ dẫn đến hành vi nguy hiểm. Bởi vì trong tiêu chuẩn cổ xưa đó, các hàm không có một nguyên mẫu có thể nhìn thấy đã chuyển đổi hoàn toàn kiểu trả về thành int. Đúc kết quả từ malloc một cách rõ ràng sau đó sẽ ẩn đi lỗi này.

    Nhưng điều đó thực sự không phải là vấn đề. Bạn không sử dụng máy tính 25 tuổi, vậy tại sao bạn lại sử dụng trình biên dịch 25 năm?


83
2018-03-20 15:53



"vô nghĩa lộn xộn" là cường điệu bất công có xu hướng làm hỏng bất kỳ khả năng thuyết phục bất cứ ai chưa đồng ý với bạn. Một diễn viên chắc chắn không phải là vô nghĩa; Câu trả lời của Ron Burk và Kaz làm cho các lập luận ủng hộ việc đúc mà tôi rất đồng ý. Cho dù những mối quan tâm nặng hơn những mối quan tâm bạn đề cập đến là một câu hỏi hợp lý để hỏi. Đối với tôi, mối quan tâm của bạn trông tương đối nhỏ so với họ. - Don Hatch
"Một con trỏ void có thể được chuyển đổi thành / từ bất kỳ loại con trỏ nào khác mà không có một diễn viên rõ ràng" không được hỗ trợ bởi 6.3.2.3. Có lẽ bạn đang nghĩ đến "con trỏ tới bất kỳ kiểu đối tượng nào"? "void pointer" và "pointer to a function" không dễ chuyển đổi như vậy. - chux
Thật vậy, tài liệu tham khảo không đầy đủ. Phần liên quan cho "người chứng kiến" là quy tắc phân công đơn giản 6.5.16.1. "một toán hạng là một con trỏ đến một kiểu đối tượng, và một là một con trỏ đến một phiên bản đủ điều kiện hoặc không đủ tiêu chuẩn của void". Tôi đã thêm tham chiếu này vào câu trả lời cho tính đầy đủ. - Lundin


Trong C bạn nhận được một chuyển đổi tiềm ẩn từ void* cho bất kỳ con trỏ (dữ liệu) nào khác.


82
2018-03-03 10:16



@ Jens: OK, có thể từ ngữ thích hợp hơn là "chuyển đổi ngầm". Giống như sử dụng biến số nguyên trong biểu thức dấu chấm động. - EFraim
@EFraim Điều đó sẽ thực sự dẫn đến một diễn viên, và một tiềm ẩn một lúc đó. - Mad Physicist


Đang truyền giá trị trả về malloc() là không cần thiết, nhưng tôi muốn thêm một điểm mà dường như không ai chỉ ra:

Trong những ngày xa xưa, đó là, trước đây ANSI C cung cấp void * là loại con trỏ chung, char * là loại cho việc sử dụng đó. Trong trường hợp đó, các diễn viên có thể tắt cảnh báo trình biên dịch.

Tài liệu tham khảo: C FAQ


62
2018-06-09 17:31



Tắt cảnh báo trình biên dịch là một ý tưởng tồi. - Albert van der Horst
@AlbertvanderHorst Không, nếu bạn đang làm như vậy bằng cách giải quyết vấn đề chính xác cảnh báo là có để cảnh báo bạn. - Dan Bechard
@Dan. Nếu bằng cách giải quyết vấn đề chính xác có nghĩa là một viết lại của một chương trình con để trả về kiểu ANSI C hiện đại thay vì char *, tôi đồng ý. Tôi sẽ không gọi là tắt trình biên dịch. Đừng cho vào các nhà quản lý, những người khẳng định rằng không có cảnh báo trình biên dịch, thay vì sử dụng chúng bằng cách biên dịch lại để tìm các vấn đề có thể xảy ra. Groetjes Albert - Albert van der Horst


Không bắt buộc phải đưa kết quả malloc, vì nó trả về void* và một void*có thể được trỏ đến bất kỳ kiểu dữ liệu nào.


48
2018-02-07 22:22





Chỉ cần thêm kinh nghiệm của tôi, nghiên cứu kỹ thuật máy tính Tôi thấy rằng hai hoặc ba giáo sư mà tôi đã thấy viết trong C luôn đúc malloc, tuy nhiên người tôi hỏi (với một CV bao la và hiểu biết về C) nói với tôi rằng nó là hoàn toàn không cần thiết nhưng chỉ được sử dụng để được hoàn toàn cụ thể, và để có được các sinh viên vào tâm lý của là hoàn toàn cụ thể. Về cơ bản việc đúc sẽ không thay đổi bất kỳ thứ gì trong cách nó hoạt động, nó thực hiện chính xác những gì nó nói, phân bổ bộ nhớ, và việc đúc không ảnh hưởng đến nó, bạn nhận được cùng một bộ nhớ, và thậm chí nếu bạn bỏ nó vào một thứ khác do nhầm lẫn (và bằng cách nào đó né tránh trình biên dịch lỗi) C sẽ truy cập nó theo cùng một cách.

Chỉnh sửa: Đúc có một điểm nhất định. Khi bạn sử dụng ký pháp mảng, mã được tạo ra phải biết có bao nhiêu vị trí bộ nhớ mà nó phải tiến tới để đạt được phần đầu của phần tử tiếp theo, điều này đạt được thông qua việc truyền. Bằng cách này bạn biết rằng đối với một đôi bạn đi 8 byte phía trước trong khi cho một int bạn đi 4, và như vậy. Do đó nó không có hiệu lực nếu bạn sử dụng ký hiệu con trỏ, trong ký pháp mảng nó trở nên cần thiết.


44
2018-03-28 18:21



Ngoại trừ như đã đề cập, các diễn viên có thể ẩn lỗi và làm cho mã khó phân tích cho trình biên dịch hoặc phân tích tĩnh. - Lundin
"Về cơ bản đúc sẽ không thay đổi bất cứ điều gì trong cách nó hoạt động". Việc truyền tới loại đối sánh sẽ không thay đổi bất cứ điều gì, nhưng thay đổi kiểu của biến thể var và diễn viên không còn phù hợp nữa, các sự cố có thể xuất hiện không? IWOs, các loại cast và var nên được giữ đồng bộ - hai lần công việc bảo trì. - chux
Tôi có thể thấy lý do tại sao các giáo sư thích đúc. Việc đúc có thể hữu ích từ quan điểm giáo dục, nơi nó truyền tải thông tin người hướng dẫn và mã sinh viên không cần phải được duy trì - mã ném đi của nó. Tuy nhiên, từ mã hóa, đánh giá ngang hàng và bảo trì quan điểm, p = malloc(sizeof *p * n); đơn giản và tốt hơn. - chux