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?

asked Aug 19 '10 at 15:05
 
 
    
possible duplicate of Error Performing Pointer Arithmetic on void * in MSVC – Carl Norum 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. – PJTraill 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. – underscore_d Aug 20 at 6:30

7 Answers

up vote 165 down vote

+100

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

GCC allows it as an extension, see Arithmetic on void- and Function-Pointers (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.

answered Aug 19 '10 at 17:05
MSadeghHE

4,32931738
 
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 extension that allows to do this. – Job Aug 19 '10 at 18:29
1  
if you no longer think your answer is useful, you can just delete it. – caf 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. – Ben Flynn 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. – Dietrich Epp May 11 '13 at 2:37
1  
what about subtracting one void pointer from another? – Michael Sep 18 '15 at 18:12

Pointer arithmetic is not allowed on void* pointers.

answered Aug 19 '10 at 15:06
Job

10.6k23063
 
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. – schot 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) – Job Aug 19 '10 at 18:39

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

answered Aug 19 '10 at 15:08
Oliver Charlesworth

185k20367520
 

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

answered Aug 19 '10 at 15:08
 
    
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. – underscore_d Aug 20 at 6:32

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

answered Aug 19 '10 at 15:08
Jakob

15.7k62751
 

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 operation char * c = (char *)p;
c++; // compiler will increment the c by 1, since size of char is 1 byte.
answered Jan 22 '13 at 5:42
 
user1581106

 
 

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)

answered Mar 13 '15 at 9:40
rytis

45348
 
    
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. – underscore_d 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. – supercat Aug 23 at 14:42

Pointer arithmetic for void pointer in C的更多相关文章

  1. differences between null pointer and void pointer.

    These are two different concepts, you cannot compare them. What the difference between the skunk and ...

  2. delete void pointer

    delete void pointer是否会有内存泄漏? 看下面一个简单例子 class Test{ public: Test(){ printf ("constructor\n" ...

  3. The Aggregate Magic Algorithms

    http://aggregate.org/MAGIC/ The Aggregate Magic Algorithms There are lots of people and places that ...

  4. Windows_Program_Via_C_Translate_Win32编程的背景知识/基础知识_包括基本输入输出机制介绍

    Some Basic Background Story of The Win32 APIs Win32 API背景故事/背景知识 The Win32 application programming i ...

  5. C++ 词汇表

    C++词汇表 A abort()                       特殊函数 如果一个函数抛出异常,但在通往异常函数的调用链中找不到与之匹配的catch,则该程序通常以此函数调用终止 abs ...

  6. C++ 命名规范小结

    1. #defines and const test.h #ifndef TEST_H #define TEST_H #endif #define FALSE 0 #define TRUE (!FAL ...

  7. 06 Frequently Asked Questions (FAQ) 常见问题解答 (常见问题)

    Frequently Asked Questions (FAQ) Origins 起源 What is the purpose of the project? What is the history ...

  8. C语言学习笔记--动态内存分配

    1. 动态内存分配的意义 (1)C 语言中的一切操作都是基于内存的. (2)变量和数组都是内存的别名. ①内存分配由编译器在编译期间决定 ②定义数组的时候必须指定数组长度 ③数组长度是在编译期就必须确 ...

  9. 《C和指针(Pointer on c)》 学习笔记(转自:http://dsqiu.iteye.com/blog/1687944)

    首先本文是对参考中三个连接的博客进行的整理,非常感谢三位博主的努力,每次都感叹网友的力量实在太强大了…… 第一章 快速上手 1.  在C语言中用/*和*/来注释掉这段代码,这个实际上并不是十分的安全, ...

随机推荐

  1. 第四课,T语言运算符(版本5.0)

    TC综合开发工具里支持了丰富的运算符,这样也要求大家对运算符的知识必须了解清楚,否则出现错误还不知道问题所在下面就为大家说说运算符的优先级与各个运算符含义 注意: 优先级代表同一表达式中运算符的运算顺 ...

  2. vimium 使用心得

    首先,建议记住chrom自己的支持的快捷键 https://support.google.com/chrome/answer/157179?hl=zh-Hans&hlrm=en-GB& ...

  3. poj1984 带权并查集

    题意:有多个点,在平面上位于坐标点上,给出一些关系,表示某个点在某个点的正东/西/南/北方向多少距离,然后给出一系列询问,表示在第几个关系给出后询问某两点的曼哈顿距离,或者未知则输出-1. 只要在元素 ...

  4. poj3660 最短路/拓扑序

    题意:有n头牛,为了给牛排顺序,给出了牛之间的胜负关系,具有传递性,问给出的胜负关系是否可以给这些牛排出唯一的顺序. 其实是个拓扑排序问题,牛的胜负关系就是有向边,然后判断是否有唯一的拓扑序就行.当然 ...

  5. android开源项目---tool篇

    本文转载于:http://blog.csdn.net/likebamboo/article/details/19080801 主要包括那些不错的开发库,包括依赖注入框架.图片缓存.网络相关.数据库OR ...

  6. 最简puremvc

    工程如下,看来sendNotification是像comand和mediator发消息的 package { import flash.display.Sprite; import flash.eve ...

  7. Linux-Nginx之sendfile与上下文切换

    今天在看nginx thread pool的时候,频繁的看到sendfile,其实以前也经常看到sendfile,只是我平时选择性的忽视而已... 先说下sendfile,明天在好好聊下nginx 线 ...

  8. ORACLE 11g 用Duplicate恢复Data Guard 备库详细过程

    1.先查找备库控制文件路径 先在备库上找出控制文件的路径,通过和主库一样,不过为了以防万一,还是check为好. SQL>  select name from v$controlfile; NA ...

  9. Entity Framework调用表值函数实现全文检索?

    CREATE FUNCTION [dbo].[udf_BookContentSearch](@keywords NVARCHAR(1000))RETURNS @BookPageDetail TABLE ...

  10. Mongo导出数据文件导致错误 Got signal: 6 (Aborted)解决方法

    一哥们要导出一个数据表的数据,结果导出一半,硬盘不够用,卡死了, 然后重启主机,导致mongo启动后进程自动死掉, 报错如下. Mon Oct 28 10:39:02.270 [initandlist ...