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. 字符串p型编码

    总时间限制:  1000ms 内存限制:  65536kB 描述 给定一个完全由数字字符('0','1','2',-,'9')构成的字符串str,请写出str的p型编码串.例如:字符串12234411 ...

  2. Codeforces Round #122 (Div. 2)

    A. Exams 枚举分数为3.4.5的数量,然后计算出2的数量即可. B. Square 相当于求\(\min{x(n+1)\ \%\ 4n=0}\) 打表发现,对\(n\ \%\ 4\)分类讨论即 ...

  3. HDU-1520 Anniversary party(树形DP)

    题目大意:一棵树,每个节点都带权.从中取出一些节点,并且子节点不能与父节点同时取,求能取得的最大值. 题目分析:定义状态dp(u,0/1)表示u点不取/取.则状态转移方程为: dp(u,1)=sum( ...

  4. Python爬虫学习笔记——豆瓣登陆(一)

    #-*- coding:utf-8 -*- import requests from bs4 import BeautifulSoup import html5lib import re import ...

  5. caffe: test code 执行出问题: Check failed: FLAGS_weights.size() > 0 (0 vs. 0) Need model weights to score.

    Check failed: FLAGS_weights.size() > 0 (0 vs. 0) Need model weights to score. 出现这个错误,但是我记得昨天还好好的, ...

  6. Valgrind使用[转]

    简介 调试程序有很多方法,例如向屏幕上打印消息,使用调试器,或者只需仔细考虑程序如何运行,并对问题进行有根有据的猜测. 在修复 bug 之前,首先要确定在源程序中的位置.例如,当一个程序产生崩溃或生成 ...

  7. MySQL 用户与授权管理详解

    大纲 一.前言 二.创建用户并授权 三.GRANT语句的种类 四.撤权并删除用户 一.前言 做为Mysql数据库管理员管理用户账户,是一件很重要的事,指出哪个用户可以连接服务器,从哪里连接,连接后能做 ...

  8. C#分部方法

    C#分部方法必须是私有的,不能返回值.分部方法主要用内部信息处理中. 下面的例子,有一个分部类People,其中一个定义一个分部方法SetDefaultValue,另外一个类中实现了其中的逻辑处理. ...

  9. 事件、委托、委托方法的总结(使用EventHandler<>)

    在C#中,定义事件.委托.委托方法可以使用类库内的EventHandler泛型委托来定义事件.并根据该泛型委托定义实现方法: 同样您也可以自定义委托 来定义事件以及 根据自定义的委托来定义实现事件的方 ...

  10. 自定的 HttpModule 为什么总是执行两次

      其实可以看一下Html页面就知道了.   其实它又请求了一次.要关了这个或者忽略之.