C 语言中空指针的概念

在 C 编程语言中,是否可以不进行类型转换而取消引用 void 指针?

还有,有没有什么方法可以泛化一个函数,它可以接收一个指针并将其存储在一个 void 指针中,通过使用 void 指针,我们可以得到一个广义函数吗?

例如:

void abc(void *a, int b)
{
if(b==1)
printf("%d",*(int*)a);     // If integer pointer is received
else if(b==2)
printf("%c",*(char*)a);     // If character pointer is received
else if(b==3)
printf("%f",*(float*)a);     // If float pointer is received
}

我想使这个函数通用而不使用 if-else 语句-这可能吗?

此外,如果有很好的互联网文章,解释了一个空指针的概念,那么它将是有益的,如果你可以提供的 URL。

另外,是否可以用空指针进行指针算法?

214135 次浏览

在 C 编程语言中,是否可以在不进行类型转换的情况下取消对 void 指针的引用..。

不,void表示没有类型,它不是你可以解引用或分配的东西。

有没有什么方法可以泛化一个可以接收指针并将其存储在 void 指针中的函数,通过使用 void 指针我们可以得到一个广义函数。.

您不能仅仅以可移植的方式取消引用它,因为它可能没有正确对齐。对于 ARM 这样的架构来说,这可能是个问题,因为指向数据类型的指针必须在数据类型大小的边界上对齐(例如,指向32位整数的指针必须在4字节的边界上对齐才能解除引用)。

例如,从 void*读取 uint16_t:

/* may receive wrong value if ptr is not 2-byte aligned */
uint16_t value = *(uint16_t*)ptr;
/* portable way of reading a little-endian value */
uint16_t value = *(uint8_t*)ptr
| ((*((uint8_t*)ptr+1))<<8);

另外,使用空指针的指针算法是否可能..。

void的指针上不能进行指针算法,因为在指针下面缺乏具体的值,因此没有指针的大小。

void* p = ...
void *p2 = p + 1; /* what exactly is the size of void?? */

不,这是不可能的。取消引用的值应该是什么类型?

在 C 语言中,void *可以转换为指向不同类型对象的指针,而无需显式强制转换:

void abc(void *a, int b)
{
int *test = a;
/* ... */

但是,这无助于以更通用的方式编写函数。

在将 void *转换为不同的指针类型时,不能对其解引用,因为解引用指针正在获取指向对象的值。裸 void不是有效类型,因此不可能解除 void *的防御。

指针算法是将指针值改为指向对象的 sizeof的倍数。同样,由于 void不是真正的类型,因此 sizeof(void)没有任何意义,所以指针算法在 void *上无效。(有些实现允许使用 char *的等效指针算法。)

我想把这个函数变成通用的, 有可能吗?

我看到的唯一简单的方法是使用重载. . 这在 C 编程语言 AFAIK 中是不可用的。

你有没有考虑过你的程序使用 C + + 编程语言? 或者有没有什么限制禁止它的使用?

void abc(void *a, int b) {
char *format[] = {"%d", "%c", "%f"};
printf(format[b-1], a);
}

您应该注意到,与 Java 或 C # 不同,在 C 中绝对不可能成功地“猜测”void*指针指向的对象类型。类似于 getClass()的东西根本不存在,因为这些信息无处可寻。由于这个原因,您所寻找的“通用”类型总是带有显式的元信息,例如示例中的 int bprintf函数族中的格式字符串。

Void 指针称为泛型指针,它可以引用任何数据类型的变量。

您可以轻松地打印空白打印机

int p=15;
void *q;
q=&p;
printf("%d",*((int*)q));

到目前为止,我对 void 指针的理解如下。

当一个指针变量使用关键字 void 声明-它成为一个通用的指针变量。任何数据类型(char、 int、 float 等)的任何变量的地址都可以赋给一个 void 指针变量。

main()
{
int *p;


void *vp;


vp=p;
}

因为其他数据类型的指针可以指定为 void 指针,所以我在绝对值(如下所示的代码)函数中使用了它。发挥一般作用。

我尝试编写一个简单的 C 代码,它以整数或浮点数作为参数,并尝试使其为 + ve,如果为负值。我写了以下代码,

#include<stdio.h>


void absolute_value ( void *j) // works if used float, obviously it must work but thats not my interest here.
{
if ( *j < 0 )
*j = *j * (-1);


}


int main()
{
int i = 40;
float f = -40;
printf("print intiger i = %d \n",i);
printf("print float f = %f \n",f);
absolute_value(&i);
absolute_value(&f);
printf("print intiger i = %d \n",i);
printf("print float f = %f \n",f);
return 0;
}

但是我出现了错误,所以我知道我对 void 指针的理解是不正确的: (。所以现在我将移动到收集点为什么是这样的。

关于 void 指针,我需要了解的是。

我们需要对 void 指针变量进行类型转换以取消对它的引用。这是因为 void 指针没有与之关联的数据类型。编译器不可能知道(或猜测?)Void 指针指向的数据类型。因此,为了获取由 void 指针指向的数据,我们使用 void 指针位置中保存的数据的正确类型对其进行类型转换。

void main()


{


int a=10;


float b=35.75;


void *ptr; // Declaring a void pointer


ptr=&a; // Assigning address of integer to void pointer.


printf("The value of integer variable is= %d",*( (int*) ptr) );// (int*)ptr - is used for type casting. Where as *((int*)ptr) dereferences the typecasted void pointer variable.


ptr=&b; // Assigning address of float to void pointer.


printf("The value of float variable is= %f",*( (float*) ptr) );


}

如果程序员不确定最终用户输入的数据的数据类型,那么 void 指针可能非常有用。在这种情况下,程序员可以使用 void 指针指向未知数据类型的位置。该程序可以设置为这样一种方式,即要求用户告知数据的类型,并且可以根据用户输入的信息进行类型转换。下面给出了一个代码片段。

void funct(void *a, int z)
{
if(z==1)
printf("%d",*(int*)a); // If user inputs 1, then he means the data is an integer and type casting is done accordingly.
else if(z==2)
printf("%c",*(char*)a); // Typecasting for character pointer.
else if(z==3)
printf("%f",*(float*)a); // Typecasting for float pointer
}

关于无效指针,您应该记住的另一个重点是-指针算法不能在无效指针中执行。

void *ptr;


int a;


ptr=&a;


ptr++; // This statement is invalid and will result in an error because 'ptr' is a void pointer variable.

所以现在我明白了我的错误,我也在纠正同样的错误。

参考文献:

Http://www.antoarts.com/void-pointers-in-c/

Http://www.circuitstoday.com/void-pointers-in-c.

New 代码如下所示。


#include<stdio.h>
#define INT 1
#define FLOAT 2


void absolute_value ( void *j, int *n)
{
if ( *n == INT) {
if ( *((int*)j) < 0 )
*((int*)j) = *((int*)j) * (-1);
}
if ( *n == FLOAT ) {
if ( *((float*)j) < 0 )
*((float*)j) = *((float*)j) * (-1);
}
}




int main()
{
int i = 0,n=0;
float f = 0;
printf("Press 1 to enter integer or 2 got float then enter the value to get absolute value\n");
scanf("%d",&n);
printf("\n");
if( n == 1) {
scanf("%d",&i);
printf("value entered before absolute function exec = %d \n",i);
absolute_value(&i,&n);
printf("value entered after absolute function exec = %d \n",i);
}
if( n == 2) {
scanf("%f",&f);
printf("value entered before absolute function exec = %f \n",f);
absolute_value(&f,&n);
printf("value entered after absolute function exec = %f \n",f);
}
else
printf("unknown entry try again\n");
return 0;
}

谢谢,

因为 C 是静态类型的强类型语言,所以在编译之前必须确定变量的类型。当您尝试在 C 中模拟泛型时,您最终将再次尝试重写 C + + ,因此最好使用 C + + 代替。

这不会起作用,但 void * 在定义指向函数的泛型指针并将其作为参数传递给另一个函数(类似于 Java 中的回调)或者定义类似于 oop 的结构方面有很大帮助。

Void 指针是一个通用指针。任何变量的任何数据类型的地址都可以赋给 void 指针。

int a = 10;
float b = 3.14;
void *ptr;
ptr = &a;
printf( "data is %d " , *((int *)ptr));
//(int *)ptr used for typecasting dereferencing as int
ptr = &b;
printf( "data is %f " , *((float *)ptr));
//(float *)ptr used for typecasting dereferencing as float

下面是一个关于 void指针的简短指针: https://www.learncpp.com/cpp-tutorial/613-void-pointers/

6.13-虚空指针

因为 void 指针不知道它所指向的对象的类型,所以不能直接取消引用它!相反,在解除引用之前,必须首先将 void 指针显式强制转换为另一种指针类型。

如果一个 void 指针不知道它指向的是什么,我们怎么知道将它强制转换到什么?归根结底,这取决于你自己。

虚空指针之类的

无法对空指针执行指针算法。这是因为指针算法要求指针知道它所指向的对象的大小,因此它可以适当地增加或减少指针。

假设机器的内存是字节可寻址的,并且不需要对齐的访问,那么解释 void*的最通用和原子(最接近机器级别的表示)方法是作为指向一个字节的指针 uint8_t*。将 void*转换为 uint8_t*将允许您,例如,打印出从该地址开始的第一个1/2/4/8/whatever-many-you-wish 字节,但是除此之外无法执行其他操作。

uint8_t* byte_p = (uint8_t*)p;
for (uint8_t* i = byte_p; i < byte_p + 8; i++) {
printf("%x ",*i);
}

基本上,在 C 语言中,“类型”是解释内存中字节的一种方法

struct Point {
int x;
int y;
};


int main() {
struct Point p;
p.x = 0;
p.y = 0;
}

说“当我运行 main 时,我想分配4(整数大小) + 4(整数大小) = 8(总字节数)的内存。当我写作的时候。X’作为编译时类型为 label Point 的值上的左值,从指针的内存位置加上4个字节检索数据。为返回值赋予编译时标签“ int”

在运行时的计算机内部,你的“ Point”结构如下:

00000000 00000000 00000000 00000000 00000000 00000000 00000000

下面是 void*数据类型可能的样子: (假设是一台32位计算机)

10001010 11111001 00010010 11000101

如果不指定指针的类型,就不能解引用指针,因为不同的数据类型在内存中的大小不同,例如 int 为4字节,char 为1字节。

空白指针是指没有与它相关联的数据类型的指针。空白指针可以保存任何类型的地址,并且可以转换为任何类型。但是,无法直接取消引用 void 指针。

int x = 1;
void *p1;
p1 = &x;
cout << *p1 << endl; // this will give error
cout << (int *)(*p) << endl; // this is valid