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. TFTP网络协议分析---15

    TFTP网络协议分析 周学伟 文档说明:所有函数都依托与两个出口,发送和接收. 1:作为发送时,要完成基于TFTP协议下的文件传输,但前提是知道木的PC机的MAC地址,因为当发送TFTP请求包时必须提 ...

  2. 数据处理项目Beta阶段软件架构建议

    class:Dataserver string serverIP string serverPassword string sqlAccount string sqlPassword bool Dat ...

  3. thinkphp 验证码的使用

    在thinkphp中使用验证码很容易,只要调用thinkphp现有的方法就可以.当然,php的GD库肯定是要开的(就是在php.ini中要加载gd模块). thinkphp 3.2 --------- ...

  4. 用vi写一个C 程序

    root@IdeaPad:~# ls 1.txt 3.txt 5.txt 6.py evilxr test 2.txt 4.txt 5.txt~ e.txt evilxr.txt root@IdeaP ...

  5. 深入理解html5系列-文本标签

    转:http://blog.csdn.net/lihui130135/article/details/45150501 文章简介:       关于html5相信大家早已经耳熟能详,但是他真正的意义在 ...

  6. Ghost的相关问题

    一些和Ghost使用有关的问题,记录在这里. 1,有时候使用ghost恢复,发现最后一步选择驱动器是灰色的,这是因为备份文件有些是用Disk模式,有些使用partition模式,所有恢复的时候如果其中 ...

  7. 黑马程序员——JAVA基础之简述 类的继承、覆写

    ------- android培训.java培训.期待与您交流! ---------- 继承的概述: 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只 ...

  8. m3u8文件简介

    1.   M3U8文件概念 M3U8文件是指UTF-8编码格式的M3U文件.M3U文件是记录了一个索引纯文本文件,打开它时播放软件并不是播放它,而是根据它的索引找到对应的音视频文件的网络地址进行在线播 ...

  9. Docker系列之(二):使用Mesos管理Docker集群(Mesos + Marathon + Chronos + Docker)

    1. Mesos简介 1.1 Mesos Apache Mesos 是一个分布式系统的管理软件,对集群的资源进行分配和管理. Mesos主要由以下几部分组成: Master: 管理各Slave节点 S ...

  10. expect安装去测试

    1.下载expect和tcl 下载地址:http://download.csdn.net/download/tobyaries/5754943 2.安装expect tar -zxvf tcl8.4. ...