博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Pointer arithmetic for void pointer in C
阅读量:5990 次
发布时间:2019-06-20

本文共 7176 字,大约阅读时间需要 23 分钟。

http://stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c

 

When a pointer to a particular type (say int, char, float, ..) is incremented, its value is increased by the size of that data type. If a void pointer which points to data of size x is incremented, how does it get to point x bytes ahead? How does the compiler know to add x to value of the pointer?

 
 
    
possible duplicate of –  Aug 19 '10 at 21:43
2  
The question sounds as though it assumes that the compiler(/run-time) knows what type of object the pointer was set to, and adds its size to the pointer. That is a complete misconception: it only knows the address. –  May 5 '15 at 21:22
    
"If a void pointer which points to data of size x is incremented, how does it get to point x bytes ahead?" It doesn't. Why can't people who have such questions test them before asking - y'know, at least to the bare minimum where they check whether it actually compiles, which this doesn't. -1, can't believe this got +100 and -0. –  Aug 20 at 6:30

7 Answers

165
+100

Final conclusion: arithmetic on a void* is illegal in both C and C++.

GCC allows it as an extension, see (note that this section is part of the "C Extensions" chapter of the manual). Clang and ICC likely allow void* arithmetic for the purposes of compatibility with GCC. Other compilers (such as MSVC) disallow arithmetic on void*, and GCC disallows it if the -pedantic-errors flag is specified, or if the -Werror-pointer-arith flag is specified (this flag is useful if your code base must also compile with MSVC).

The C Standard Speaks

Quotes are taken from the n1256 draft.

The standard's description of the addition operation states:

6.5.6-2: For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type.

So, the question here is whether void* is a pointer to an "object type", or equivalently, whether void is an "object type". The definition for "object type" is:

6.2.5.1: Types are partitioned into object types (types that fully describe objects) , function types (types that describe functions), and incomplete types (types that describe objects but lack information needed to determine their sizes).

And the standard defines void as:

6.2.5-19: The void type comprises an empty set of values; it is an incomplete type that cannot be completed.

Since void is an incomplete type, it is not an object type. Therefore it is not a valid operand to an addition operation.

Therefore you cannot perform pointer arithmetic on a void pointer.

Notes

Originally, it was thought that void* arithmetic was permitted, because of these sections of the C standard:

6.2.5-27: A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.

However,

The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.

So this means that printf("%s", x) has the same meaning whether x has type char* or void*, but it does not mean that you can do arithmetic on a void*.

Editor's note: This answer has been edited to reflect the final conclusion.

 
6  
From the C99 standard: (6.5.6.2) For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type. (6.2.5.19) The void type comprises an empty set of values; it is an incomplete type that cannot be completed. I think that makes it clear that void* pointer arithmetic is not allowed. GCC has an that allows to do this. –  Aug 19 '10 at 18:29
1  
if you no longer think your answer is useful, you can just delete it. –  Aug 20 '10 at 1:28
1  
This answer was useful even though it proved wrong as it contains conclusive proof that void pointers aren't meant for arithmetic. –  Oct 17 '12 at 21:48
1  
This is a good answer, it has the right conclusion and the necessary citations, but people who came to this question came to the wrong conclusion because they didn't read to the bottom of the answer. I've edited this to make it more obvious. –  May 11 '13 at 2:37
1  
what about subtracting one void pointer from another? –  Sep 18 '15 at 18:12

48

Pointer arithmetic is not allowed on void* pointers.

 
11  
+1 Pointer arithmetic is only defined for pointers to (complete) object types. void is an incomplete type that can never be completed by definition. –  Aug 19 '10 at 15:33
1  
@schot: Exactly. Moreover, pointer arithmetic is only defined on a pointer to an element of an array object and only if the result of the operation would be a pointer to an element in that same array or one past the last element of that array. If those conditions are not met, it is undefined behavior. (From C99 standard 6.5.6.8) –  Aug 19 '10 at 18:39

12

You can't do pointer arithmetic on void * types, for exactly this reason!

 

12

cast it to a char pointer an increment your pointer forward x bytes ahead.

 
    
Why bother? Just cast it to the right type - which should always be known - and increment that by 1. Casting to char, incrementing by x, and then reinterpreting the new value as some other type is both pointless and undefined behaviour. –  Aug 20 at 6:32

6

You have to cast it to another type of pointer before doing pointer arithmetic.

 

3

Void pointers can point to any memory chunk. Hence the compiler does not know how many bytes to increment/decrement when we attempt pointer arithmetic on a void pointer. Therefore void pointers must be first typecast to a known type before they can be involved in any pointer arithmetic.

void *p = malloc(sizeof(char)*10);p++; //compiler does how many where to pint the pointer after this increment operationchar * c = (char *)p;c++;  // compiler will increment the c by 1, since size of char is 1 byte.
 

-1

Compiler knows by type cast. Given a void *x:

  • x+1 adds one byte to x, pointer goes to byte x+1
  • (int*)x+1 adds sizeof(int) bytes, pointer goes to byte x + sizeof(int)
  • (float*)x+1 addres sizeof(float) bytes, etc.

Althought the first item is not portable and is against the Galateo of C/C++, it is nevertheless C-language-correct, meaning it will compile to something on most compilers possibly necessitating an appropriate flag (like -Wpointer-arith)

 
    
Althought the first item is not portable and is against the Galateo of C/C++ True. it is nevertheless C-language-correct False. This is doublethink! Pointer arithmetic on void * is syntactically illegal, should not compile, and produces undefined behaviour if it does. If a careless programmer can make it compile by disabling some warning, that's no excuse. –  Aug 20 at 6:35
    
@underscore_d: I think some compilers used to allow it as an extension, since it's a lot more convenient than having to cast to unsigned char* to e.g. add a sizeof value to a pointer. –  Aug 23 at 14:42

转载地址:http://vtjlx.baihongyu.com/

你可能感兴趣的文章
「docker实战篇」python的docker爬虫技术-fiddler抓包工具(三)
查看>>
【今日头条】【抖音&火山】算法实习生
查看>>
java流的中间操作源码解析
查看>>
Android开发 - 掌握ConstraintLayout(二)介绍
查看>>
EOS开发完全解析(一):Ubuntu上搭建EOS开发环境
查看>>
安全研究人员:可绕过Gatekeeper安全机制macOS漏洞
查看>>
Facebook 与 150 家企业共享用户数据,且未告知用户
查看>>
百度iOS面试
查看>>
Python基础教程:Day15-图像和办公文档处理
查看>>
Bytom设计结构解读
查看>>
比原链合约入门教程
查看>>
条码插件TBarCode Office系列教程三(Excel Add-In篇)
查看>>
微软随用随付供Azure成本管理服务
查看>>
数据库管理系统Microsoft SQL Server 2019(预览版)发布!
查看>>
Android 音视频录制硬编码实现
查看>>
从裂变到成为产品的增长黑客,我们又破了纪录:4天增长1万用户
查看>>
前端必修课:ES2017+下的构建工具原理与实战
查看>>
第九期 杭州 NodeParty x 贝贝集团 技术分享——诚邀您报名参加
查看>>
一次 Cocoa App(macOS App)开发尝试
查看>>
Android 事件分发机制
查看>>