簡體   English   中英

將 function 返回到 function 返回 void 指針的 object 指針是否合法?

[英]Is it legal to cast a function returning an object pointer to a function returning a void pointer?

這些部分表明調用具有不兼容類型的 function 指針會導致未定義的行為。

C89 3.5.4.3 p9

對於要兼容的兩個 function 類型,兩者都應指定兼容的返回類型 此外,參數類型列表(如果兩者都存在)應在參數數量和省略號終止符的使用方面達成一致; 相應的參數應具有兼容的類型。

C89 3.5.4.1 p2

對於要兼容的兩種指針類型,兩者都應具有相同的限定,並且都應是指向兼容類型的指針。

C89 3.3.4 p3

指向一種類型的 function 的指針可以轉換為指向另一種類型的 function 的指針,然后再返回; 結果應與原始指針比較。 如果使用轉換后的指針調用 function 的類型與被調用的 function 的類型不兼容,則行為未定義。

從任何其他 object 指針類型轉換為 void 指針是否兼容?

C89 3.3.4 p3

It is guaranteed, however, that a pointer to an object of a given alignment may be converted to a pointer to an object of the same alignment or a less strict alignment and back again; 結果應與原始指針比較。 (具有字符類型的 object 具有最不嚴格的 alignment。)

C89 3.1.2.5 p20

指向 void 的指針應具有與指向字符類型的指針相同的表示形式和 alignment 要求。

C89 3.2.2.3 p1

指向 void 的指針可以轉換為指向任何不完整或 object 類型的指針或從指針轉換。 指向任何不完整或 object 類型的指針可以轉換為指向 void 的指針並再次返回; 結果應與原始指針比較。

例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int *foo(void) {
    int *data = malloc(sizeof(int));
    *data = 42;
    return data;
}

int main(int argc, char *argv[]) {
    void *(*fn_ptr)(void) = foo;
    void *raw = fn_ptr();
    int data = *(int *)raw;
    printf("%d\n", data);
}

您問將指向 function 的指針轉換為指向 function 的另一個指針是否合法。 將指向 function 的指針轉換為指向 function 的任何其他指針是合法的。 但是通過這樣的指針調用 function 會調用未定義的行為。 C11 6.5.2.2p9

6.5.2.2 Function 調用

[...]

  1. 如果 function 定義的類型與表示被調用的 function 的表達式所指向的(表達式的)類型不兼容,則行為未定義。

另一個問題是您的代碼沒有演員表。 它有一個強制分配:

void *(*fn_ptr)(void) = foo;

這是無效的,違反了約束,C 編譯器必須診斷。 演員會讀

void *(*fn_ptr)(void) = (void *(*)(void))foo;

現在的問題是

void *(*fn_ptr)(void) = (void *(*)(void))foo;
void *raw = fn_ptr();
int data = *(int *)raw;

根據標准未定義構造的行為。 當然,您的實現可以自由地為表達式提供含義。 在這種情況下,您應該檢查您的編譯器手冊以了解該行為。

有些架構中void *int *的表示將不兼容。


如果您只是將 function 指針更改為返回int *或在調用之前強制轉換的指針,則行為是明確定義的 - 隱式轉換為void *和顯式轉換為int *都很好。

IE

int *(*fn_ptr)(void) = foo;
void *raw = fn_ptr();
int data = *(int *)raw;

或者

void *(*fn_ptr)(void) = (void *(*)(void))foo;
void *raw = ((int *(*)(void))fn_ptr)();
int data = *(int *)raw;

或者讓 function 返回void *

void *foo(void) {
    int *data = malloc(sizeof(int));
    *data = 42;
    return data;
}

void *(*fn_ptr)(void) = foo;
void *raw = fn_ptr();
int data = *(int *)raw;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM