2017-06-24 12 views
9

Nếu tôi đang viết một thuật toán chung, tôi có được phép đặt bí danh một mảng kiểu không xác định làm con trỏ tới một mảng trong đó mỗi phần tử là kích thước được cung cấp mà không cần gọi hành vi không xác định?Truy cập các mục mảng thông thường qua con trỏ tới mảng ký tự?

Ví dụ: có UB trong mã sau không?

typedef void (*action_t)(const void *item); 
void do(void *array, size_t eltCount, size_t eltSize, action_t action) 
{ 

    // Convenient typedef. 
    typedef char element[eltSize]; 
    element *elts = array; 
    element *end = elts + eltCount; 

    for (; elts != end; elts++) { 
     action(elts); 
    } 
} 

Tôi biết tôi có thể làm điều này:

char *elts = array; 
char *end = elts + eltCount * eltSize; 

for (; elts != end; elts += eltSize) { 
    action(elts); 
} 

Nhưng bit đầu tiên của mã dường như nhiều thành ngữ với tôi kể từ khi trình biên dịch hiện số học con trỏ cho tôi. Hàm trên biên dịch không có cảnh báo bằng cả gcc và clang (cờ biên dịch có liên quan là -std=c99 -O3 -fstrict-aliasing -pedantic-errors -Wextra -Wall). Tôi cũng tự hỏi về việc đánh răng nghiêm ngặt, nhưng theo như tôi có thể nói, có vẻ như tôi không phá vỡ nó ở đây vì các đối tượng được phép được sử dụng gián tiếp qua char*.

+0

Ví dụ sau của bạn sẽ chuyển một char duy nhất đến một hàm mong muốn một con trỏ để trống, ít nhất. Một lỗi đánh máy? –

+0

@ IljaEverilä Đã sửa lỗi. Cảm ơn bạn –

+0

Nếu bạn gặp rắc rối thì 'qsort()' và 'bsearch()' cũng vậy .., –

Trả lời

1

Trong C, typedef không giới thiệu loại mới. Nó chỉ đặt tên một cấu trúc. Tên và định nghĩa của nó có thể hoán đổi cho nhau. (Điều này cũng không đúng đối với, ví dụ: struct, nơi không có cách nào để thể hiện định nghĩa của cấu trúc khác với tên của nó.)

Vì vậy, miễn là bạn chỉ nói về một số hình thức char * - như bạn đã biết, là đặc biệt bởi vì bất kỳ con trỏ dữ liệu nào cũng có thể được chuyển đổi thành nó - thì bạn đang dựa vào hành vi được xác định.

Các vấn đề liên quan