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. Xcode7.0.1(ios9)的部分适配问题

    今天更新了Xcode 7 正式版,App编译出现很多警告,在App运行的时候出现如下的提示......... the resource could not be loaded because the ...

  2. kuangbin_ShortPath D (POJ 3268)

    本来在想 单源多点很好解决但是多源单点怎么解 然后我发现只要倒过来就可以了 把输入存下来然后 处理完dis1 重新init一次 倒着再输入一次 处理dis2 输出max(dis1[i] + dis2[ ...

  3. ToDictionary,ToLookup

    这个系列我们看看C#中有哪些我们知道,但是又不知道怎么用,又或者懒得去了解的东西,比如这篇我们要介绍的toDictionary 和ToLookup. 从图中我们看到有四个ToXXX的方法,其中ToAr ...

  4. Sublime Text 下配置python

    Sublime Text 2作为一款轻量级的编辑器,特点鲜明,方便使用,而且支持多语言.  一.control+B方式 1. 在工具栏点击Preferences,打开Browse Packages.在 ...

  5. Myeclipse10中出现Cannot return from outside a function or method错误提示

    最近发现myeclipse10中有几处bug 比如: Cannot return from outside a function or method onClick="return chec ...

  6. 如何将SQL Server 2008库导入2000中

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  7. 将m个苹果放入n个盘子的问题【转】

    来自:http://blog.csdn.net/qq675927952/article/details/6312255 问题1: m----->相同, n---> 相同,可为空 将m个苹果 ...

  8. swagger-editor 快速REST-API 测试文档编写

    1. 在线使用 http://editor.swagger.io/#/ 2. 离线工具 https://github.com/swagger-api/swagger-editor 3. 跨域访问问题: ...

  9. fastBinaryJSON

    fastBinaryJSON 是基于 fastJSON 的二进制 JSON 序列化器.详细介绍请看这里. 数据编码格式: 序列化速度比较:

  10. vs2010 clickone 工程安装后的路径 win7

    C:\Users\xuan\AppData\Local\Apps\2.0\DX16T5JV.MLO\1H1ZAND1.1ZY\test..tion_f74974f651f2573b_0001.0000 ...