[英]Void** as parameter requires cast
我在C中有一個函數,需要接收一個指向數組的指針(具有未指定的類型)。
為此,我使用void **,因為我將使用void *來接收未指定元素的數組。
不幸的是,存在一個問題:編譯器發出警告(從不兼容的指針類型傳遞參數1'f')。 如果我忽略該警告,並嘗試執行該程序,那么一切都會按預期進行。
擺脫警告的唯一方法是將我嘗試傳遞給函數的所有內容強制轉換為void **。
為什么C會那樣表現? 還有解決警告的更好方法嗎?
PS:我需要使用帶有標志-std = gnu89 -pedantic -Wall的GCC進行編譯
例
int f(void** param){ return 1; }
int main(){
int *arr = malloc(sizeof(int) * 20);
int i;
for(i=0; i < 20; i++) arr[i] = i;
f(&arr);
}
指向任何類型的指針都是void*
,並且編譯器將不會抱怨對該類型的轉換。 但是void**
不是指向任何東西的指針,它是指向任何東西的指針數組的指針,這與指向整數的指針數組的指針有很大的不同,因此編譯器會抱怨。 因此,要解決該警告,是的,您需要顯式強制轉換。
似乎您想修改函數內的數據地址(而不是值),您不能直接使用void *
來完成此操作,因為您不能對void *
使用算術運算,但是可以傳遞第一元件和字節的塊( char *
),假設要更改的地址arr
到arr + 1
在函數內部(所述陣列的所述第二元素):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void f(void *ptr, size_t size)
{
// char *p = *ptr; Wrong, you can't dereference a void * without a cast
char *p = *(char **)ptr; /* pointer to address of ptr */
memmove(p, p + size, size); /* assign the address of ptr + 1 to ptr */
}
int main(void)
{
int *arr = malloc(sizeof(int) * 20);
int i;
for (i = 0; i < 20; i++) arr[i] = i;
f(&arr, sizeof arr[0]);
printf("%d\n", arr[0]);
return 0;
}
輸出:
1
盡管void *
是C語言中的“通用指針”,但void **
不是“指針通用指針”。 相反,它只不過是“指向void *
特定指針,即通用指針”。
在您的情況下, int **
隱式轉換為void **
,這不是通用的。 由於不能保證void **
能夠容納所有指針變量(因此與int **
不兼容),因此編譯器會發出警告。
這是clang生成的警告:
main.c:7:7: warning: incompatible pointer types passing 'int **' to parameter of
type 'void **' [-Wincompatible-pointer-types]
f(&arr);
^~~~
main.c:1:14: note: passing argument to parameter 'param' here
int f(void** param){ return 1; }
要消除此警告,可以使用int f(void* param);
,並將param
轉換為函數內的int **
。 將不會發出警告,因為可以使用void *
來存儲任何指針(引自N1570):
6.3.2.3指針
1指向void的指針可以轉換為任何對象類型的指針,也可以將其轉換為任何對象類型的指針。 指向任何對象類型的指針都可以轉換為void指針,然后再返回; 結果應等於原始指針。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.